在使用TextView的時候,咱們常常須要在TextView中進行圖文混排,好比在QQ中聊天的消息中的表情,底部tab圖標等。html
Android官方對TextView的圖文混排提供了支持,咱們能夠從如下三種方式實現TextView的圖文混排:java
1.在TextView中使用Compound Drawable屬性;
2.在TextView中使用Spannable多樣式顯示;
3.在TextView中顯示HTML文本。android
在TextView中使用Compound Drawable屬性能夠在文字的上下左右放置drawable,效果以下:
git
<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 | 圖片和文字的間距 |
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 | 設置圖片與文字之間的間距 |
當TextView設置成固定大小時,因爲文字距離邊界的距離過大,會致使文字與圖片之間設置的間距無效,以下圖。
web
①設置TextView的內填充bash
經過設置paddingLeft、paddingRight、paddingTop、paddingBottom來縮寫這個間距網絡
②自定義TextView從新佈局異步
a.先自定義屬性iconPadding來設置間距,並提供方法給外部調用。工具
b.重寫setCompoundDrawablesWithIntrinsicBounds()方法來獲取咱們設置的drawable寬高。
c.最後重寫onLayout方法。
能夠先參考:Android技巧之drawablePadding的那些事,該篇文章只解決了左右失效的問題。後期會整理個解決圖文混排的工具庫,裏面會有具體方案。
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。
經常使用類 | 說明 |
---|---|
BackgroundColorSpan | 背景色樣式,顯然能夠用來設定文本的背景色 |
ForegroundColorSpan | 字體顏色樣式,用於改變字體顏色 |
StyleSpan | 主要由正常、粗體、斜體和同時加粗傾斜四種樣式 |
TypefaceSpan | 設置不一樣的字體 |
ImageSpan | 圖片樣式,主要用於在文本中插入圖片 |
URLSpan | 能夠打開一個連接 |
UnderlineSpan | 下劃線樣式 |
StrikethroughSpan | 刪除線樣式 |
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。很惋惜咱們日常用的居中對其的方式沒有,不過能夠經過自定義實現,後續會在開源出來。
通常顯示HTML內容有兩種方式:
如今大多數都用WebView的方式。可是並非全部的場景下都適合使用 WebView 來顯示 HTML 內容,例如,若是應用要顯示的內容只是一部分 HTML 片斷,就能夠利用 TextView 來進行顯示,而且效率較高。
因爲這種方式不太經常使用,就不深刻介紹,裏面能夠實現的效果仍是很好的。
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 內容即包含超連接內容,也包含有圖片。
fromHtml方法
fromHtml(String source, ImageGetter imageGetter,TagHandler tagHandler)複製代碼
繼承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方法來實現。
關於HTML顯示這部分,沒作具體實現。具體能夠看:靈活高效的在 Android Native App 開發中顯示 HTML 內容,裏面有具體源碼能夠下載,HTML部份內容也是參考該篇文章完成的。
開源庫:html-textview
以上就是關於圖文混排的一些解決方案,相信經過這些瞭解,對於工做中的實際場景的使用你們會有適當的解決方案。因爲實際應用較少,因此認識較爲淺顯,可能有些地方描述不當,後期會考慮封裝個解決圖文混排的工具類,加深下理解。