編輯:關於Android編程
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()方法被調用。就可以在這個方法中進行跳轉了。
socket編程是網絡通信的一個基礎應用,無論是手機端還是PC端都需要socket技術來建立網絡通信。在本章小編主要從以下幾個方面來介紹socket的相關知識:分別是&l
網站中為了防止惡意獲取驗證短信、驗證郵箱,都會在點擊獲取驗證碼的按鈕上做個倒計時的效果,如何實現這個效果,具體內容如下效果圖: 代碼:RegisterActiv
這次做一個圖片加載器,裡面涉及到線程池,bitmap的高效加載,LruCache,DiskLruCache。接下來我先介紹這四個知識點一.線程池優點:(1)重用線程池中的
1 概述這裡我們會詳細講解matrix的各個方法,以及它的用法。matrix叫做矩陣,在前面講解 ColorFilter 的文章中,我們講解了ColorMatrix,他是