1. 程式人生 > >Android-如何讓優雅地讓一個TextView顯示兩種樣式的字型

Android-如何讓優雅地讓一個TextView顯示兩種樣式的字型

分享優雅寫程式碼的一個小技巧~

前言

這是一個很常見的需求,一般出現在有單位的資料展示上面。例如下面的兩個例子,來源於我司專案的某一個頁面。

如果讓你實現圖一的3.07萬元 和圖二的 您的估價低於 80% 車主的估價,你會怎麼佈局?

如果是以前的我:

圖一的3.07萬元 會換成 3.07萬元 兩個 TextView 顯示,因為倆大小不一樣,這個理由尚能接受。

圖二,會換成 3 個 TextView 顯示,因為顏色不一樣,而且顏色不一樣的還在中間。嗯,這個說出來就感覺有點丟臉了。

然而現在我想說,事實上,這兩者都可以只用一個 TextView 展示。

而且方式還不只一種:

  • TextView 顯示 Html 樣式
  • SpannableString

下面分別用這兩種方式實現一下。

Html 方式

有這麼一個方法:

Html.fromHtml()

該方法可以將一段 html 字串顯示為TextView 可以顯示的樣式文字。

於是,首先根據需求編寫好 html ,通過該方法轉換文字,拿給 TextView 顯示即可。

如下:

tv1.setText(Html.fromHtml("<font color=\'#217aff\' ><big>3.07</big></font><font color
=\'#217aff\' >
<small>萬元</small></font>")); tv2.setText(Html.fromHtml("<font color=\'#656565\'>您的估價</font><font color=\'#f48421\'>低於</font><font color=\'#656565\'>80%車主的售價。</font>"));

顯示效果:

另外,大家注意到上面 3.07萬元中兩個字型大小不同,我是通過 <big>3.07</big>

<small>萬元</small> 去控制的。這個是因為 Android 中只支援 標籤的 color 和 face 標籤,不支援 size 標籤。所以像下面的樣式,無法顯示 size 大小的。

"<font color=\'#217aff\' size=\'18px\' >3.07</font><font color=\'#217aff\' size=\'10px\'>萬元</font>"

想控制大小隻能通過 <big><small> 標籤,但是兩者的大小比較固定,沒辦法精確控制。如果遇到需要控制字型大小的需求,可以考慮用下面的 SpannableString 來實現。

SpannableString 方式

SpannableString 實現了 CharSequence 介面,所以無須轉換, TextView 可以直接通過 setText() 方法顯示。

先使用 SpannableString 實現上面的例子感受一下:

// “3.07 萬元”的實現方式
SpannableString s1 = new SpannableString("3.07萬元");

s1.setSpan(new AbsoluteSizeSpan(18, true), 0, s1.length()-2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
s1.setSpan(new AbsoluteSizeSpan(10, true), s1.length()-2, s1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

tv3.setTextColor(Color.parseColor("#217aff"));
tv3.setText(s1);

// “80%車主的估價”的實現方式
SpannableString s2 = new SpannableString("您的估價低於80%車主的估價");

s2.setSpan(new ForegroundColorSpan(Color.parseColor("#656565")), 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
s2.setSpan(new ForegroundColorSpan(Color.parseColor("#f48421")), 4, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
s2.setSpan(new ForegroundColorSpan(Color.parseColor("#656565")), 6, s2.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

tv4.setText(s2);

顯示效果:

是不是很贊,來看一下實現過程:

第一步:建立一個SpannableString。

SpannableString spannableString = new SpannableString("3.07萬元");

第二步:使用 setSpan() 給 SpannableString 設定樣式。

spannableString.setSpan(Object what, int start, int end, int flags);

引數的意義是:

  • what:對SpannableString進行潤色的各種Span;
  • start:需要潤色文欄位開始的下標;
  • end:需要潤色文欄位結束的下標;
  • flags:標誌位,決定操作的範圍是否包含開始和結束下標,有四個引數可選,為什麼有四個?因為分別代表著 start 至 end 的四種集合開閉模式。
    • SPAN_INCLUSIVE_EXCLUSIVE:[start,end) 包括開始下標,但不包括結束下標
    • SPAN_EXCLUSIVE_INCLUSIVE:(start,end] 不包括開始下標,但包括結束下標
    • SPAN_INCLUSIVE_INCLUSIVE:[start,end] 既包括開始下標,又包括結束下標
    • SPAN_EXCLUSIVE_EXCLUSIVE:(start,end) 不包括開始下標,也不包括結束下標

總體是第一個引數決定效果,後三個引數決定範圍,顯而易見,第一個引數是非常的需要去好好認識,把酒言歡一下的。

SpannableString 提供了很多 Span 樣式供開發者們選擇,有用來設定大小,顏色,下劃線,甚至還有點選事件的。我找了它們的繼承結構圖,截來給大家看一下 Span 們的家譜。

上面例子中只用到了兩個樣式, ForegroundColorSpan 設定字型前景顏色,AbsoluteSizeSpan 設定字型大小,非常的簡單。其實 Span 們功能遠不止這些,但是這裡不贅述了,大家可以自己多去嘗試,下面是我覺得比較好的文章連結分享。

另外一個新 Get 的小知識點

真實的專案開發中,想 3.07萬元 這種字串不可能是固定好的,肯定是有服務端返回的,但是有的只是純數字。那麼除了用 + 號拼接,還可以這樣使用:

 String s = String.format("%s萬元",3.07);

關於這個 String.format() 方法也是最近才發現的一個小技巧,使用上感覺比+要更方便,也更直觀,關於它的更多資訊可以直接看官方文件,大概瞭解掌握其功能,記住幾個最常用的,其他的可以隨用隨查。

最後

哈哈哈,覺得自己之前好笨拙,可能現在也是,不過有這個感覺也證明現在變的好一點了吧,雖然是一個很小的知識點。荀子老人家說了:“不積跬步,無以至千里;不積小流,無以成江海。”,希望我們都越來越好。

下篇部落格見。


歡迎關注博主的微信公眾號,快快加入哦,期待與你一起成長!