Android中的TextView,本身就支持部分的Html格式标签。这其中包括常用的字体大小颜色设置,文本链接等。使用起来也比较方便,只需要使用Html类转换一下即可。比如:
textView.setText(Html.fromHtml(str));
然而,有一种场合,默认支持的标签可能不够用。比如,我们需要在textView中点击某种链接,返回到应用中的某个界面,而不仅仅是网络连接,如何实现?
经过几个小时对android中的Html类源代码的研究,找到了解决办法,并且测试通过。
先看Html类的源代码中有这样一段:
-
-
-
-
-
public static interface TagHandler {
-
-
-
-
-
public void handleTag(boolean opening, String tag,
-
Editable output, XMLReader xmlReader);
这里定义了一个接口,接口用于什么呢?
再继续看代码,看到对Html的tag进行解析部分的代码:
-
private void handleStartTag(String tag, Attributes attributes) {
-
if (tag.equalsIgnoreCase("br")) {
-
-
-
} 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()方法被调用。就可以在这个方法中进行跳转了。
http://blog.csdn.net/arui319/article/details/6709424