在使用TextView的時候乡翅,我們經(jīng)常需要在TextView中進(jìn)行圖文混排鳞疲,比如在QQ中聊天的消息中的表情,底部tab圖標(biāo)等峦朗。
一建丧、場景
二、實現(xiàn)方式
Android官方對TextView的圖文混排提供了支持波势,我們可以從以下三種方式實現(xiàn)TextView的圖文混排:
1.在TextView中使用Compound Drawable屬性翎朱;
2.在TextView中使用Spannable多樣式顯示;
3.在TextView中顯示HTML文本尺铣。
三拴曲、drawable屬性
在TextView中使用Compound Drawable屬性可以在文字的上下左右放置drawable,效果如下:
一共有兩種方式可以實現(xiàn):XML布局設(shè)置和Java代碼設(shè)置凛忿。
1. xml布局
<TextView
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查看新的內(nèi)容"
android:textSize="18sp"
android:drawablePadding="10dp"
android:drawableLeft="@drawable/arrow"/>
android:drawableLeft | 在文字左邊設(shè)置圖片 |
---|---|
android:drawableTop | 在文字上邊設(shè)置圖片 |
android:drawableRight | 在文字右邊設(shè)置圖片 |
android:drawableBottom | 在文字下邊設(shè)置圖片 |
android:drawableStart | API 17后生效澈灼,LTR時在左邊,RTL時在右邊 |
android:drawableEnd | API 17后生效店溢,LTR時在右邊叁熔,RTL時在左邊 |
android:drawablePadding | 圖片和文字的間距 |
2. java代碼
textView = (TextView) findViewById(R.id.textView);
Drawable drawable = getResources().getDrawable(R.drawable.see);
drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
textView.setCompoundDrawables(null,null,null,drawable);
textView.setCompoundDrawablePadding(10);
注意:必須setBounds()測量圖片邊界,否則不顯示床牧。
setCompoundDrawables | 設(shè)置上下左右位置的圖片 |
---|---|
setCompoundDrawablesRelative | 設(shè)置四周的圖片荣回,其中兩邊對應(yīng)xml中的start,end |
setCompoundDrawablesWithIntrinsicBounds | 設(shè)置上下左右位置的圖片,圖片有默認(rèn)的邊界 |
setCompoundDrawablesRelativeWithIntrinsicBounds | 設(shè)置四周的圖片戈咳,圖片有默認(rèn)的邊界 |
setCompoundDrawablePadding | 設(shè)置圖片與文字之間的間距 |
3.缺陷
當(dāng)TextView設(shè)置成固定大小時心软,由于文字距離邊界的距離過大,會導(dǎo)致文字與圖片之間設(shè)置的間距無效著蛙,如下圖删铃。
解決方案:
①設(shè)置TextView的內(nèi)填充
通過設(shè)置paddingLeft、paddingRight踏堡、paddingTop猎唁、paddingBottom來縮寫這個間距
②自定義TextView重新布局
a.先自定義屬性iconPadding來設(shè)置間距,并提供方法給外部調(diào)用顷蟆。
b.重寫setCompoundDrawablesWithIntrinsicBounds()方法來獲取我們設(shè)置的drawable寬高胖秒。
c.最后重寫onLayout方法缎患。
可以先參考:Android技巧之drawablePadding的那些事,該篇文章只解決了左右失效的問題。后期會整理個解決圖文混排的工具庫阎肝,里面會有具體方案。
四肮街、Spannable使用
1.簡介
setText(CharSequence text)中接收的是CharSequence风题。而SpannableString和SpannableStringBuilder是其實現(xiàn)類,是可以直接賦值的嫉父。并且兩者的setSpan()方法可以設(shè)置一些格式對象(例如字體大小沛硅、下劃線、替換為圖片等)绕辖,這就可以實現(xiàn)富文本了摇肌。
Spannable實現(xiàn)子類:SpannableString,SpannableStringBuilder(可變仪际,類似于StringBuilder)围小。
Spannable中定義了抽象方法:setSpan(Object what, int start, int end, int flags)和removeSpan(Object what)。這兩個方法實現(xiàn)了對字符串的靈活編輯树碱。
其中setSpan()方法包含如下參數(shù):
參數(shù) | 參數(shù)說明 |
---|---|
what | span樣式 |
start | 樣式開始的索引 |
end | 樣式結(jié)束的索引 |
flags | 樣式作用的范圍 |
flags常用的有四種
SPAN_INCLUSIVE_INCLUSIVE | 前后都包括肯适,在指定范圍前后插入新字符,都會應(yīng)用新樣式 |
---|---|
SPAN_EXCLUSIVE_EXCLUSIVE | 前后都不包括成榜,在指定范圍前后插入新字符框舔,兩端樣式無變化 |
SPAN_INCLUSIVE_EXCLUSIVE | 前面包括,后面不包括 |
SPAN_EXCLUSIVE_INCLUSIVE | 后面包括赎婚,前面不包括 |
通常在insert方式才生效刘绣,平時不生效,具體看:Explain the meaning of Span flags like SPAN_EXCLUSIVE_EXCLUSIVE挣输。
2.常用span類
常用類 | 說明 |
---|---|
BackgroundColorSpan | 背景色樣式纬凤,顯然可以用來設(shè)定文本的背景色 |
ForegroundColorSpan | 字體顏色樣式,用于改變字體顏色 |
StyleSpan | 主要由正常歧焦、粗體移斩、斜體和同時加粗傾斜四種樣式 |
TypefaceSpan | 設(shè)置不同的字體 |
ImageSpan | 圖片樣式,主要用于在文本中插入圖片 |
URLSpan | 可以打開一個鏈接 |
UnderlineSpan | 下劃線樣式 |
StrikethroughSpan | 刪除線樣式 |
3.使用方式
SpannableString span3 = new SpannableString("我如果愛你");
ImageSpan image = new ImageSpan(this,R.drawable.collect, DynamicDrawableSpan.ALIGN_BOTTOM);
span3.setSpan(image,3,4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv3.setText(span3);
其中ImageSpan默認(rèn)對其方式有兩種:ALIGN_BOTTOM及ALIGN_BASELINE绢馍。很可惜我們平常用的居中對其的方式?jīng)]有向瓷,不過可以通過自定義實現(xiàn),后續(xù)會在開源出來舰涌。
4.效果
五猖任、HTML顯示
一般顯示HTML內(nèi)容有兩種方式:
- 使用 Android 提供的 WebView 控件。
- 通過將 HTML 內(nèi)容轉(zhuǎn)化為 Spanned 格式在 TextView 中進(jìn)行顯示瓷耙。
現(xiàn)在大多數(shù)都用WebView的方式朱躺。但是并不是所有的場景下都適合使用 WebView 來顯示 HTML 內(nèi)容刁赖,例如,如果應(yīng)用要顯示的內(nèi)容只是一部分 HTML 片段长搀,就可以利用 TextView 來進(jìn)行顯示宇弛,并且效率較高。
由于這種方式不太常用源请,就不深入介紹枪芒,里面可以實現(xiàn)的效果還是很好的。
1.簡介
Android 中的 TextView 組件常用于顯示文本內(nèi)容谁尸,其實它也可以顯示 HTML 的內(nèi)容舅踪。
簡單來講,這就需要先把 HTML 的內(nèi)容以字符串的形式獲取后良蛮,經(jīng)過 android.text.Html.fromHtml()轉(zhuǎn)化成 Spanned 的格式抽碌,然后將其傳遞到 TextView 的 setText()方法中,這樣就可以在 TextView 中顯示 HTML 頁面的內(nèi)容了决瞳。
需要注意的是货徙,并不是所有的 HTML 標(biāo)簽在 TextView 中都是支持的,且官方文檔并沒有明確的說明支持 HTML 標(biāo)簽列表瞒斩,通過查看 Android 源代碼破婆,可以得到簡單的支持列表。
,< p>,< div align=>,< strong>, <b>, <em>, <cite>, <dfn>, <i>, <big>, <small>, <font size=>, <font color=>, <blockquote>, <tt>, <a href=>,
<u>, , , <h1>,<h2>,<h3>,<h4>,<h5>,<h6>, <img src=>, <strike>
下面的示例來介紹如何在 TextView 中顯示一段 HTML 內(nèi)容胸囱,要顯示的這段 HTML 內(nèi)容即包含超鏈接內(nèi)容祷舀,也包含有圖片。
2.使用
fromHtml方法
fromHtml(String source, ImageGetter imageGetter,TagHandler tagHandler)
- source烹笔,就是包含 HTML 內(nèi)容的字符串裳扯。Html.ImageGetter 和 Html.TagHandler 是兩個接口,提供給開發(fā)者繼承使用谤职。
- imageGetter饰豺, 如果要顯示圖片是需要被繼承的,重寫 getDrawable(String source)方法允蜈,用于獲取 HTML 里面的圖片來顯示在 TextView 中冤吨。
- tagHandler,其作用是把 HTML 帶標(biāo)記的文本內(nèi)容字符串轉(zhuǎn)化成可以顯示效果的的 Spanned 字符串 饶套。由于并非所有的 HTML 標(biāo)簽都可以轉(zhuǎn)化漩蟆,所以在使用時,用戶需要自己添加一些必要的標(biāo)簽和處理方法時才會繼承使用的妓蛮。
繼承ImageGetter
繼承于 ImageGetter怠李,重寫 getDrawable (String source) 方法。通過異步操作,讀取本地/網(wǎng)絡(luò)資源捺癞,獲得drawable對象夷蚊。
繼承TagHandler
繼承于 TagHandler,重寫了 handleTag()方法髓介。為了支持更多的標(biāo)簽惕鼓,例如為了支持<ul><ol><dd>和<li>標(biāo)簽,這四個標(biāo)簽是在 formHtml()方法中本身是不支持唐础。
如果開發(fā)者認(rèn)為安卓 TagHandler 提供的默認(rèn)標(biāo)簽解析已經(jīng)夠用彻犁,直接在 fromHtml()方法中第三個參數(shù)的地方填寫 null 既可。
最后,通過 formHtml()方法將 HTML 內(nèi)容轉(zhuǎn)化為可供顯示的 SpannableString仲智,將 SpannableString 通過 setText 方法放入 TextView 中肴焊,就可以顯示圖文并茂的內(nèi)容了娶眷。
用戶交互
formHtml()方法已經(jīng)將 HTML 內(nèi)容中的超鏈接和圖片轉(zhuǎn)義成為 UrlSpan 和 ImageSpan烁落,進(jìn)而在 TextView 中完成顯示。但是此時是沒有任何用戶交互的,用戶只能看到 HTML 的內(nèi)容熊痴,下面介紹如何添加用戶交互功能诊笤。
要完成用戶交互鄙煤,這里我們需要在 TextView 中還需要調(diào)用textView.setMovementMethod()方法凉馆。
Android 提供了 LinkMovementMethod 類以實現(xiàn)了對于文本內(nèi)容中超鏈接的遍歷,并且支持對于超鏈接的點擊事件。
所以只要在添加下面一行代碼京革,就可以使點擊 UrlSpan 能夠觸發(fā)打開鏈接的功能。
textView.setMovementMethod(LinkMovementMethod.getInstance())
如果想要更多的用戶交互效果来惧,可以自定義LinkMovementMethod 類,重寫onTouchEvent方法來實現(xiàn)葛虐。
3.效果
點擊圖片,跳轉(zhuǎn)到圖片詳情頁万栅。
關(guān)于HTML顯示這部分扰她,沒做具體實現(xiàn)。具體可以看:靈活高效的在 Android Native App 開發(fā)中顯示 HTML 內(nèi)容,里面有具體源碼可以下載窖壕,HTML部分內(nèi)容也是參考該篇文章完成的廉涕。
開源庫:html-textview
轉(zhuǎn)自:http://www.reibang.com/p/6843f332c8df