Android圖文混排實(shí)現(xiàn)方式詳解

在使用TextView的時(shí)候,我們經(jīng)常需要在TextView中進(jìn)行圖文混排,比如在QQ中聊天的消息中的表情,底部tab圖標(biāo)等。

一、場景

image

二、實(shí)現(xiàn)方式

Android官方對TextView的圖文混排提供了支持,我們可以從以下三種方式實(shí)現(xiàn)TextView的圖文混排:

1.在TextView中使用Compound Drawable屬性;
2.在TextView中使用Spannable多樣式顯示;
3.在TextView中顯示HTML文本。

三、drawable屬性

在TextView中使用Compound Drawable屬性可以在文字的上下左右放置drawable,效果如下:

image

一共有兩種方式可以實(shí)現(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時(shí)在左邊,RTL時(shí)在右邊
android:drawableEnd API 17后生效,LTR時(shí)在右邊,RTL時(shí)在左邊
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è)置成固定大小時(shí),由于文字距離邊界的距離過大,會(huì)導(dǎo)致文字與圖片之間設(shè)置的間距無效,如下圖。

image

解決方案:

①設(shè)置TextView的內(nèi)填充

通過設(shè)置paddingLeft、paddingRight、paddingTop、paddingBottom來縮寫這個(gè)間距

②自定義TextView重新布局

a.先自定義屬性iconPadding來設(shè)置間距,并提供方法給外部調(diào)用。

b.重寫setCompoundDrawablesWithIntrinsicBounds()方法來獲取我們設(shè)置的drawable寬高。

c.最后重寫onLayout方法。

可以先參考:Android技巧之drawablePadding的那些事,該篇文章只解決了左右失效的問題。后期會(huì)整理個(gè)解決圖文混排的工具庫,里面會(huì)有具體方案。

四、Spannable使用

1.簡介

setText(CharSequence text)中接收的是CharSequence。而SpannableString和SpannableStringBuilder是其實(shí)現(xiàn)類,是可以直接賦值的。并且兩者的setSpan()方法可以設(shè)置一些格式對象(例如字體大小、下劃線、替換為圖片等),這就可以實(shí)現(xiàn)富文本了。

Spannable實(shí)現(xiàn)子類:SpannableString,SpannableStringBuilder(可變,類似于StringBuilder)。

Spannable中定義了抽象方法:setSpan(Object what, int start, int end, int flags)和removeSpan(Object what)。這兩個(gè)方法實(shí)現(xiàn)了對字符串的靈活編輯。

其中setSpan()方法包含如下參數(shù):

參數(shù) 參數(shù)說明
what span樣式
start 樣式開始的索引
end 樣式結(jié)束的索引
flags 樣式作用的范圍

flags常用的有四種

SPAN_INCLUSIVE_INCLUSIVE 前后都包括,在指定范圍前后插入新字符,都會(huì)應(yīng)用新樣式
SPAN_EXCLUSIVE_EXCLUSIVE 前后都不包括,在指定范圍前后插入新字符,兩端樣式無變化
SPAN_INCLUSIVE_EXCLUSIVE 前面包括,后面不包括
SPAN_EXCLUSIVE_INCLUSIVE 后面包括,前面不包括

通常在insert方式才生效,平時(shí)不生效,具體看:Explain the meaning of Span flags like SPAN_EXCLUSIVE_EXCLUSIVE

2.常用span類

常用類 說明
BackgroundColorSpan 背景色樣式,顯然可以用來設(shè)定文本的背景色
ForegroundColorSpan 字體顏色樣式,用于改變字體顏色
StyleSpan 主要由正常、粗體、斜體和同時(shí)加粗傾斜四種樣式
TypefaceSpan 設(shè)置不同的字體
ImageSpan 圖片樣式,主要用于在文本中插入圖片
URLSpan 可以打開一個(gè)鏈接
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)]有,不過可以通過自定義實(shí)現(xiàn),后續(xù)會(huì)在開源出來。

4.效果

image

五、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)行顯示,并且效率較高。

由于這種方式不太常用,就不深入介紹,里面可以實(shí)現(xiàn)的效果還是很好的。

1.簡介

Android 中的 TextView 組件常用于顯示文本內(nèi)容,其實(shí)它也可以顯示 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 是兩個(gè)接口,提供給開發(fā)者繼承使用。
  • imageGetter, 如果要顯示圖片是需要被繼承的,重寫 getDrawable(String source)方法,用于獲取 HTML 里面的圖片來顯示在 TextView 中。
  • tagHandler,其作用是把 HTML 帶標(biāo)記的文本內(nèi)容字符串轉(zhuǎn)化成可以顯示效果的的 Spanned 字符串 。由于并非所有的 HTML 標(biāo)簽都可以轉(zhuǎn)化,所以在使用時(shí),用戶需要自己添加一些必要的標(biāo)簽和處理方法時(shí)才會(huì)繼承使用的。

繼承ImageGetter

繼承于 ImageGetter,重寫 getDrawable (String source) 方法。通過異步操作,讀取本地/網(wǎng)絡(luò)資源,獲得drawable對象。

繼承TagHandler

繼承于 TagHandler,重寫了 handleTag()方法。為了支持更多的標(biāo)簽,例如為了支持<ul><ol><dd>和<li>標(biāo)簽,這四個(gè)標(biāo)簽是在 formHtml()方法中本身是不支持。

如果開發(fā)者認(rèn)為安卓 TagHandler 提供的默認(rèn)標(biāo)簽解析已經(jīng)夠用,直接在 fromHtml()方法中第三個(gè)參數(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 中完成顯示。但是此時(shí)是沒有任何用戶交互的,用戶只能看到 HTML 的內(nèi)容,下面介紹如何添加用戶交互功能。

要完成用戶交互,這里我們需要在 TextView 中還需要調(diào)用textView.setMovementMethod()方法。

Android 提供了 LinkMovementMethod 類以實(shí)現(xiàn)了對于文本內(nèi)容中超鏈接的遍歷,并且支持對于超鏈接的點(diǎn)擊事件。

所以只要在添加下面一行代碼,就可以使點(diǎn)擊 UrlSpan 能夠觸發(fā)打開鏈接的功能。

textView.setMovementMethod(LinkMovementMethod.getInstance())

如果想要更多的用戶交互效果,可以自定義LinkMovementMethod 類,重寫onTouchEvent方法來實(shí)現(xiàn)。

3.效果

image

點(diǎn)擊圖片,跳轉(zhuǎn)到圖片詳情頁。

關(guān)于HTML顯示這部分,沒做具體實(shí)現(xiàn)。具體可以看:靈活高效的在 Android Native App 開發(fā)中顯示 HTML 內(nèi)容,里面有具體源碼可以下載,HTML部分內(nèi)容也是參考該篇文章完成的。
開源庫:html-textview

轉(zhuǎn)自:http://www.itdecent.cn/p/6843f332c8df

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容