Android中为TextView增加自定义的HTML标签
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
?Android中的TextView,本身就支持部分的Html格式標(biāo)簽。這其中包括常用的字體大小顏色設(shè)置,文本鏈接等。使用起來(lái)也比較方便,只需要使用Html類(lèi)轉(zhuǎn)換一下即可。比如:
textView.setText(Html.fromHtml(str));
?
然而,有一種場(chǎng)合,默認(rèn)支持的標(biāo)簽可能不夠用。比如,我們需要在textView中點(diǎn)擊某種鏈接,返回到應(yīng)用中的某個(gè)界面,而不僅僅是網(wǎng)絡(luò)連接,如何實(shí)現(xiàn)?
?
經(jīng)過(guò)幾個(gè)小時(shí)對(duì)android中的Html類(lèi)源代碼的研究,找到了解決辦法,并且測(cè)試通過(guò)。
?
先看Html類(lèi)的源代碼中有這樣一段:
/*** 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); }
?
這里定義了一個(gè)接口,接口用于什么呢?
?
再繼續(xù)看代碼,看到對(duì)Html的tag進(jìn)行解析部分的代碼:
?
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);}}
?
可以看到,如果不是默認(rèn)的標(biāo)簽,會(huì)調(diào)用mTagHandler的handleTag方法。所以,我們可以實(shí)現(xiàn)此接口,來(lái)解析自己定義的標(biāo)簽類(lèi)型。
?
再看一段我實(shí)現(xiàn)的對(duì)<game>標(biāo)簽進(jìn)行解析的示例代碼:
public class GameTagHandler implements TagHandler {private int startIndex = 0;private int stopIndex = 0;@Overridepublic 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 {@Overridepublic void onClick(View v) {// 跳轉(zhuǎn)某頁(yè)面}}
?
上面這段代碼,是對(duì)<game>…</game>的自定義標(biāo)簽進(jìn)行解析。
?
具體調(diào)用方法:
?????? textView.setText(Html.fromHtml(“點(diǎn)擊<game>這里</game>跳轉(zhuǎn)到游戲”,
????????????? null, new GameTagHandler()));
?????? textView.setClickable(true);
?????? textView.setMovementMethod(LinkMovementMethod.getInstance());
?
運(yùn)行后,能夠看到文本中的字符串“這里”帶了超鏈接,點(diǎn)擊鏈接后,GameSpan類(lèi)的onClick()方法被調(diào)用。就可以在這個(gè)方法中進(jìn)行跳轉(zhuǎn)了。
?
原文鏈接: http://blog.csdn.net/arui319/article/details/6709424
轉(zhuǎn)載于:https://my.oschina.net/liux/blog/50432
總結(jié)
以上是生活随笔為你收集整理的Android中为TextView增加自定义的HTML标签的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C#委托的异步调用
- 下一篇: 简单点儿、简单点儿、再简单点儿,其实世界