广

android开发

  • IOS开发
  • android开发
  • PHP编程
  • JavaScript
  • ASP.NET
  • ASP编程
  • JSP编程
  • Java编程
  • 易语言
  • Ruby编程
  • Perl编程
  • AJAX
  • 正则表达式
  • C语言
  • 编程开发

    解析在Android中为TextView增加自定义HTML标签的实现方法

    2018-04-07 07:49:25 次阅读 稿源:互联网
    广告

    Android中的TextView,本身就支持部分的Html格式标签。这其中包括常用的字体大小颜色设置,文本链接等。使用起来也比较方便,只需要使用Html类转换一下即可。比如:

    textView.setText(Html.fromHtml(str));

    然而,有一种场合,默认支持的标签可能不够用。比如,我们需要在textView中点击某种链接,返回到应用中的某个界面,而不仅仅是网络连接,如何实现?

    经过几个小时对android中的Html类源代码的研究,找到了解决办法,并且测试通过。

    先看Html类的源代码中有这样一段:
    代码如下:

    /**
        * Is notified when HTML tags are encountered that the parser does
        * not know how to interpret.
        */ 
       public static interface TagHandler { 
           /**
            * This method will be called whenn the HTML parser encounters
            * a tag that it does not know how to interpret.
            */ 
           public void handleTag(boolean opening, String tag, 
                                    Editable output, XMLReader xmlReader); 

    这里定义了一个接口,接口用于什么呢?

    再继续看代码,看到对Html的tag进行解析部分的代码:
    代码如下:

    private void handleStartTag(String tag, Attributes attributes) { 
            if (tag.equalsIgnoreCase("br")) { 
                // We don't need to handle this. TagSoup will ensure that there's a </br> for each <br>  
                // so we can safely emite the linebreaks when we handle the close tag.  
            } else if (tag.equalsIgnoreCase("p")) { 
                handleP(mSpannableStringBuilder); 
            } else if (tag.equalsIgnoreCase("div")) { 
                handleP(mSpannableStringBuilder); 
            } else if (tag.equalsIgnoreCase("em")) { 
                start(mSpannableStringBuilder, new Bold()); 
            } else if (tag.equalsIgnoreCase("b")) { 
                start(mSpannableStringBuilder, new Bold()); 
            } else if (tag.equalsIgnoreCase("strong")) { 
                start(mSpannableStringBuilder, new Italic()); 
            } else if (tag.equalsIgnoreCase("cite")) { 
                start(mSpannableStringBuilder, new Italic()); 
            } else if (tag.equalsIgnoreCase("dfn")) { 
                start(mSpannableStringBuilder, new Italic()); 
            } else if (tag.equalsIgnoreCase("i")) { 
                start(mSpannableStringBuilder, new Italic()); 
            } else if (tag.equalsIgnoreCase("big")) { 
                start(mSpannableStringBuilder, new Big()); 
            } else if (tag.equalsIgnoreCase("small")) { 
                start(mSpannableStringBuilder, new Small()); 
            } else if (tag.equalsIgnoreCase("font")) { 
                startFont(mSpannableStringBuilder, attributes); 
            } else if (tag.equalsIgnoreCase("blockquote")) { 
                handleP(mSpannableStringBuilder); 
                start(mSpannableStringBuilder, new Blockquote()); 
            } else if (tag.equalsIgnoreCase("tt")) { 
                start(mSpannableStringBuilder, new Monospace()); 
            } else if (tag.equalsIgnoreCase("a")) { 
                startA(mSpannableStringBuilder, attributes); 
            } else if (tag.equalsIgnoreCase("u")) { 
                start(mSpannableStringBuilder, new Underline()); 
            } else if (tag.equalsIgnoreCase("sup")) { 
                start(mSpannableStringBuilder, new Super()); 
            } else if (tag.equalsIgnoreCase("sub")) { 
                start(mSpannableStringBuilder, new Sub()); 
            } else if (tag.length() == 2 && 
                       Character.toLowerCase(tag.charAt(0)) == 'h' && 
                       tag.charAt(1) >= '1' && tag.charAt(1) <= '6') { 
                handleP(mSpannableStringBuilder); 
                start(mSpannableStringBuilder, new Header(tag.charAt(1) - '1')); 
            } else if (tag.equalsIgnoreCase("img")) { 
                startImg(mSpannableStringBuilder, attributes, mImageGetter); 
            } else if (mTagHandler != null) { 
                mTagHandler.handleTag(true, tag, mSpannableStringBuilder, mReader); 
            } 
        } 

        private void handleEndTag(String tag) { 
            if (tag.equalsIgnoreCase("br")) { 
                handleBr(mSpannableStringBuilder); 
            } else if (tag.equalsIgnoreCase("p")) { 
                handleP(mSpannableStringBuilder); 
            } else if (tag.equalsIgnoreCase("div")) { 
                handleP(mSpannableStringBuilder); 
            } else if (tag.equalsIgnoreCase("em")) { 
                end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD)); 
            } else if (tag.equalsIgnoreCase("b")) { 
                end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD)); 
            } else if (tag.equalsIgnoreCase("strong")) { 
                end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 
            } else if (tag.equalsIgnoreCase("cite")) { 
                end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 
            } else if (tag.equalsIgnoreCase("dfn")) { 
                end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 
            } else if (tag.equalsIgnoreCase("i")) { 
                end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 
            } else if (tag.equalsIgnoreCase("big")) { 
                end(mSpannableStringBuilder, Big.class, new RelativeSizeSpan(1.25f)); 
            } else if (tag.equalsIgnoreCase("small")) { 
                end(mSpannableStringBuilder, Small.class, new RelativeSizeSpan(0.8f)); 
            } else if (tag.equalsIgnoreCase("font")) { 
                endFont(mSpannableStringBuilder); 
            } else if (tag.equalsIgnoreCase("blockquote")) { 
                handleP(mSpannableStringBuilder); 
                end(mSpannableStringBuilder, Blockquote.class, new QuoteSpan()); 
            } else if (tag.equalsIgnoreCase("tt")) { 
                end(mSpannableStringBuilder, Monospace.class, 
                        new TypefaceSpan("monospace")); 
            } else if (tag.equalsIgnoreCase("a")) { 
                endA(mSpannableStringBuilder); 
            } else if (tag.equalsIgnoreCase("u")) { 
                end(mSpannableStringBuilder, Underline.class, new UnderlineSpan()); 
            } else if (tag.equalsIgnoreCase("sup")) { 
                end(mSpannableStringBuilder, Super.class, new SuperscriptSpan()); 
            } else if (tag.equalsIgnoreCase("sub")) { 
                end(mSpannableStringBuilder, Sub.class, new SubscriptSpan()); 
            } else if (tag.length() == 2 && 
                    Character.toLowerCase(tag.charAt(0)) == 'h' && 
                    tag.charAt(1) >= '1' && tag.charAt(1) <= '6') { 
                handleP(mSpannableStringBuilder); 
                endHeader(mSpannableStringBuilder); 
            } else if (mTagHandler != null) { 
                mTagHandler.handleTag(false, tag, mSpannableStringBuilder, mReader); 
            } 
        } 

    可以看到,如果不是默认的标签,会调用mTagHandler的handleTag方法。所以,我们可以实现此接口,来解析自己定义的标签类型。

    再看一段我实现的对<game>标签进行解析的示例代码:
    代码如下:

    public class GameTagHandler implements TagHandler { 
        private int startIndex = 0; 
        private int stopIndex = 0; 
        @Override 
        public void handleTag(boolean opening, String tag, Editable output, 
                XMLReader xmlReader) { 
            if (tag.toLowerCase().equals("game")) { 
                if (opening) { 
                    startGame(tag, output, xmlReader); 
                } else { 
                    endGame(tag, output, xmlReader); 
                } 
            }  

        } 
        public void startGame(String tag, Editable output, XMLReader xmlReader) { 
            startIndex = output.length(); 
        } 

        public void endGame(String tag, Editable output, XMLReader xmlReader) { 
            stopIndex = output.length(); 
            output.setSpan(new GameSpan(), startIndex, stopIndex, 
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
        } 

        private class GameSpan extends ClickableSpan implements OnClickListener { 

            @Override 
            public void onClick(View v) { 
                // 跳转某页面  
            } 
        }

    上面这段代码,是对<game>…</game>的自定义标签进行解析。

    具体调用方法:

           textView.setText(Html.fromHtml(“点击<game>这里</game>跳转到游戏”,

                  null, new GameTagHandler()));

           textView.setClickable(true);

           textView.setMovementMethod(LinkMovementMethod.getInstance());

    运行后,能够看到文本中的字符串“这里”带了超链接,点击链接后,GameSpan类的onClick()方法被调用。就可以在这个方法中进行跳转了。

    一起学吧部分文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与一起学吧进行文章共享合作。

    广告
    广告
    广告