1. TextView 中嵌套圖片的方法
TextView textView... textView.setText("..."); textView.append(Html.fromHtml("<imgsrc='"+R.drawable.question+"'/>",imageGetter, new MTagHandler(context)));
就是在 TextView 中加入包含圖片的 html 代碼。
Html.fromHtml(String source, ImageGetter imageGetter, TagHandler tagHandler)
- 其中 source 里面放 html 代碼,里面加入圖片的資源ID(R.id.xxx)。
- ImageGetter 是一個接口,里面有抽象方法 public Drawable getDrawable(String source); 用來獲取圖片的 Drawable 對象(可以從網絡,或 res 資源,或本地文件獲取,本例中從 res 中獲取)。
- TagHandler 是一個接口,用來處理 html 標簽。當我們遇到一個 html 標簽后,做相應的處理工作,比如點擊的響應。
2. TextView 中嵌套圖片的點擊響應
ImageGetter 的實現:
ImageGetter imageGetter = new ImageGetter() { @Override public Drawable getDrawable(String source) { int id = Integer.parseInt(source); Drawable drawable = context.getResources().getDrawable(id); drawable.setBounds(int left, int top, int right, int bottom); return drawable; } };
TagHandler 的實現:
public class MTagHandler implements TagHandler { private int sIndex = 0; private int eIndex = 0; private final Context mContext; public MTagHandler(Context context) { mContext = context; } public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) { // TODO Auto-generated method stub if (tag.toLowerCase().equals("img")) { if (opening) { sIndex = output.length(); } else { eIndex = output.length(); output.setSpan(new MSpan(), sIndex, eIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } } private class MSpan extends ClickableSpan implements OnClickListener { @Override public void onClick(View widget) { // TODO Auto-generated method stub Log.e("test", "aaaaaaaaaaaa"); Toast.makeText(context, "sdfdsfsdfdsf", 1000).show(); } } }
碰到 img 標簽后做 onClick 里的響應處理。
最后,非常重要的一件事,就是要給 TextView 做個設置,否則點擊不會相應。
textView.setMovementMethod(LinkMovementMethod.getInstance());
3. TextView 中部分文字的點擊相應
這里需要使用 SpannableString(不可變) 或 SpannableStringBuilder(可變)。
首先,創建一個 SpannbleString:
SpannableString spannableString = new SpannableString("xxxx");
spannableString.setSpan(Object what, int start, int end, int flags);
Object what 這里放一個 ClickableSpan,並實現它的 onClick 方法用於點擊相應。
int start,int end 定義字符串的區間。
int flags 表示樣式。在 Spanned 類中有很多參數可供使用。常用的是 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
spannableString.setSpan(new ClickableSpan() { @Override public void onClick(View widget) { // TODO Auto-generated method stub // 要做的事寫在這里 } },0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
然后把 TextView 的文字內容設置為 SpannbleString:
textView.setText(spannableString);
最后,同樣的,非常重要的一件事,就是要給 TextView 做個設置,否則點擊不會相應。
textView.setMovementMethod(LinkMovementMethod.getInstance());
4. TextView 中改變部分文字的顏色或背景顏色等
添加圖片(不需要點擊響應的話)可以用 ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
改變部分文字顏色或背景:
mTextView = (TextView)findViewById(R.id.test); SpannableString s = new SpannableString(mTextView.getText()); s.setSpan(new BackgroundColorSpan(Color.RED), 0, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //紅色高亮 s.setSpan(new UnderlineSpan(), 15, 18,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //下划線
s.setSpan(new ForegroundColorSpan(Color.RED), 0, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //字體紅色
s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), 2, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //斜體加黑 mTextView.setText(s);
一篇不錯的寫 SpannbleString 的文章:
http://ezfantasy.iteye.com/blog/1468631
http://www.apkbus.com/forum.php?mod=viewthread&tid=18983
5. TextView 中遇到的一個有趣的Bug
在一次實際應用中。我做了一個答題的程序。答了的題的標題前加上一個對號表示這個題回答過了。
我開始是這樣做的:
SpannableString s = new SpannableString("✔ " + textTitle.getText()); s.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.custom_theme_color_green)), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); textTitle.setText(s);
我另外有一個函數用來刪除標題前的對號用來表示此題回答了之后又被取消了。
真正出現的問題是:
我的 TextView 里加入過一個內嵌的小圖片按鈕,詳情見最上面。然后當我添加/刪除 小對號 "✔ " 之后,我的圖片按鈕突然不見了。
原因:
帶有 Span 的 TextView 的文字內容是 CharSequence 類型。為了讓里面包含的 Span 不丟失,不可以對它進行類型轉換。所以當我們進行添加對號時,必須用 TextView 的 append() 函數。像上面代碼寫的,文字內容被轉換為 SpannableString 了,然后 Span 丟失了。為什么會這樣呢,看了一下 SpannableString 的構造函數的源碼才知道,new SpannableString(CharSequence source) 的時候,里面的 CharSequence 被執行了 source.toString(); 而 Span 就是這么丟的。
那么解決方法呢:
- 添加對號:
SpannableString s = new SpannableString("✔ "); s.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.custom_theme_color_green)), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); CharSequence c = textTitle.getText(); textTitle.setText(s); textTitle.append(c);
- 刪除對號:
textTitle.setText(textTitle.getText().subSequence(2, textTitle.getText().length()));