Android中怎么给TextView增加自定义HTML标签

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 for each

  

            // 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)             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)             handleP(mSpannableStringBuilder); 

            endHeader(mSpannableStringBuilder); 

        } else if (mTagHandler != null) { 

            mTagHandler.handleTag(false, tag, mSpannableStringBuilder, mReader); 

        } 

    } 

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

 

再看一段我实现的对

标签进行解析的示例代码:

 

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) { 

            // 跳转某页面  

        } 

    }

上面这段代码,是对


的自定义标签进行解析。

 

具体调用方法:

       textView.setText(Html.fromHtml(“点击

这里
跳转到游戏”,

              null, new GameTagHandler()));

       textView.setClickable(true);

       textView.setMovementMethod(LinkMovementMethod.getInstance());

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

以上就是爱站技术频道小编为大家详细讲解的关于在Android中为TextView增加自定义HTML标签的实现方法,当碰到默认的标签不够时,就用以上方法去增加吧。