Android圖文混排實現方式詳解

在使用TextView的時候,咱們常常須要在TextView中進行圖文混排,好比在QQ中聊天的消息中的表情,底部tab圖標等。html

1、場景

2、實現方式

Android官方對TextView的圖文混排提供了支持,咱們能夠從如下三種方式實現TextView的圖文混排:java

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

3、drawable屬性

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


一共有兩種方式能夠實現:XML佈局設置和Java代碼設置。

1. xml佈局

<TextView
        android:gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="查看新的內容"
        android:textSize="18sp"
        android:drawablePadding="10dp"
        android:drawableLeft="@drawable/arrow"/>複製代碼
android:drawableLeft 在文字左邊設置圖片
android:drawableTop 在文字上邊設置圖片
android:drawableRight 在文字右邊設置圖片
android:drawableBottom 在文字下邊設置圖片
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()測量圖片邊界,不然不顯示。github

setCompoundDrawables 設置上下左右位置的圖片
setCompoundDrawablesRelative 設置四周的圖片,其中兩邊對應xml中的start,end
setCompoundDrawablesWithIntrinsicBounds 設置上下左右位置的圖片,圖片有默認的邊界
setCompoundDrawablesRelativeWithIntrinsicBounds 設置四周的圖片,圖片有默認的邊界
setCompoundDrawablePadding 設置圖片與文字之間的間距

3.缺陷

當TextView設置成固定大小時,因爲文字距離邊界的距離過大,會致使文字與圖片之間設置的間距無效,以下圖。
web

解決方案:

①設置TextView的內填充bash

經過設置paddingLeft、paddingRight、paddingTop、paddingBottom來縮寫這個間距網絡

②自定義TextView從新佈局異步

a.先自定義屬性iconPadding來設置間距,並提供方法給外部調用。工具

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

c.最後重寫onLayout方法。

能夠先參考:Android技巧之drawablePadding的那些事,該篇文章只解決了左右失效的問題。後期會整理個解決圖文混排的工具庫,裏面會有具體方案。

4、Spannable使用

1.簡介

setText(CharSequence text)中接收的是CharSequence。而SpannableString和SpannableStringBuilder是其實現類,是能夠直接賦值的。而且二者的setSpan()方法能夠設置一些格式對象(例如字體大小、下劃線、替換爲圖片等),這就能夠實現富文本了。

Spannable實現子類:SpannableString,SpannableStringBuilder(可變,相似於StringBuilder)。

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

其中setSpan()方法包含以下參數:

參數 參數說明
what span樣式
start 樣式開始的索引
end 樣式結束的索引
flags 樣式做用的範圍

flags經常使用的有四種

SPAN_INCLUSIVE_INCLUSIVE 先後都包括,在指定範圍先後插入新字符,都會應用新樣式
SPAN_EXCLUSIVE_EXCLUSIVE 先後都不包括,在指定範圍先後插入新字符,兩端樣式無變化
SPAN_INCLUSIVE_EXCLUSIVE 前面包括,後面不包括
SPAN_EXCLUSIVE_INCLUSIVE 後面包括,前面不包括

一般在insert方式才生效,平時不生效,具體看:Explain the meaning of Span flags like SPAN_EXCLUSIVE_EXCLUSIVE

2.經常使用span類

經常使用類 說明
BackgroundColorSpan 背景色樣式,顯然能夠用來設定文本的背景色
ForegroundColorSpan 字體顏色樣式,用於改變字體顏色
StyleSpan 主要由正常、粗體、斜體和同時加粗傾斜四種樣式
TypefaceSpan 設置不一樣的字體
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默認對其方式有兩種:ALIGN_BOTTOM及ALIGN_BASELINE。很惋惜咱們日常用的居中對其的方式沒有,不過能夠經過自定義實現,後續會在開源出來。

4.效果

5、HTML顯示

通常顯示HTML內容有兩種方式:

  • 使用 Android 提供的 WebView 控件。
  • 經過將 HTML 內容轉化爲 Spanned 格式在 TextView 中進行顯示。

如今大多數都用WebView的方式。可是並非全部的場景下都適合使用 WebView 來顯示 HTML 內容,例如,若是應用要顯示的內容只是一部分 HTML 片斷,就能夠利用 TextView 來進行顯示,而且效率較高。

因爲這種方式不太經常使用,就不深刻介紹,裏面能夠實現的效果仍是很好的。

1.簡介

Android 中的 TextView 組件經常使用於顯示文本內容,其實它也能夠顯示 HTML 的內容。

簡單來說,這就須要先把 HTML 的內容以字符串的形式獲取後,通過 android.text.Html.fromHtml()轉化成 Spanned 的格式,而後將其傳遞到 TextView 的 setText()方法中,這樣就能夠在 TextView 中顯示 HTML 頁面的內容了。

須要注意的是,並非全部的 HTML 標籤在 TextView 中都是支持的,且官方文檔並無明確的說明支持 HTML 標籤列表,經過查看 Android 源代碼,能夠獲得簡單的支持列表。

<br>,< p>,< div align=>,< strong>, <b>, <em>, <cite>, <dfn>, <i>, <big>, <small>, <font size=>, <font color=>, <blockquote>, <tt>, <a href=>,
<u>, <sup>, <sub>, <h1>,<h2>,<h3>,<h4>,<h5>,<h6>, <img src=>, <strike>複製代碼

下面的示例來介紹如何在 TextView 中顯示一段 HTML 內容,要顯示的這段 HTML 內容即包含超連接內容,也包含有圖片。

2.使用

fromHtml方法

fromHtml(String source, ImageGetter imageGetter,TagHandler tagHandler)複製代碼
  • source,就是包含 HTML 內容的字符串。Html.ImageGetter 和 Html.TagHandler 是兩個接口,提供給開發者繼承使用。
  • imageGetter, 若是要顯示圖片是須要被繼承的,重寫 getDrawable(String source)方法,用於獲取 HTML 裏面的圖片來顯示在 TextView 中。
  • tagHandler,其做用是把 HTML 帶標記的文本內容字符串轉化成能夠顯示效果的的 Spanned 字符串 。因爲並不是全部的 HTML 標籤均可以轉化,因此在使用時,用戶須要本身添加一些必要的標籤和處理方法時纔會繼承使用的。

繼承ImageGetter

繼承於 ImageGetter,重寫 getDrawable (String source) 方法。經過異步操做,讀取本地/網絡資源,得到drawable對象。

繼承TagHandler

繼承於 TagHandler,重寫了 handleTag()方法。爲了支持更多的標籤,例如爲了支持<ul><ol><dd><li>標籤,這四個標籤是在 formHtml()方法中自己是不支持。

若是開發者認爲安卓 TagHandler 提供的默認標籤解析已經夠用,直接在 fromHtml()方法中第三個參數的地方填寫 null 既可。

最後,經過 formHtml()方法將 HTML 內容轉化爲可供顯示的 SpannableString,將 SpannableString 經過 setText 方法放入 TextView 中,就能夠顯示圖文並茂的內容了。

用戶交互

formHtml()方法已經將 HTML 內容中的超連接和圖片轉義成爲 UrlSpan 和 ImageSpan,進而在 TextView 中完成顯示。可是此時是沒有任何用戶交互的,用戶只能看到 HTML 的內容,下面介紹如何添加用戶交互功能。

要完成用戶交互,這裏咱們須要在 TextView 中還須要調用textView.setMovementMethod()方法。

Android 提供了 LinkMovementMethod 類以實現了對於文本內容中超連接的遍歷,而且支持對於超連接的點擊事件。

因此只要在添加下面一行代碼,就可使點擊 UrlSpan 可以觸發打開連接的功能。

textView.setMovementMethod(LinkMovementMethod.getInstance())複製代碼

若是想要更多的用戶交互效果,能夠自定義LinkMovementMethod 類,重寫onTouchEvent方法來實現。

3.效果


點擊圖片,跳轉到圖片詳情頁。

關於HTML顯示這部分,沒作具體實現。具體能夠看:靈活高效的在 Android Native App 開發中顯示 HTML 內容,裏面有具體源碼能夠下載,HTML部份內容也是參考該篇文章完成的。
開源庫:html-textview

6、總結

以上就是關於圖文混排的一些解決方案,相信經過這些瞭解,對於工做中的實際場景的使用你們會有適當的解決方案。因爲實際應用較少,因此認識較爲淺顯,可能有些地方描述不當,後期會考慮封裝個解決圖文混排的工具類,加深下理解。

相關文章
相關標籤/搜索