作者:孟校長
連結:https://www.jianshu.com/p/699a8cae05ce
前言
上一篇文章還是今年四月份寫的,期間也嘗試寫過幾篇文章, 但是都因繁忙的工作只能暫時的放下。此刻其實手上還是有很多需求沒有完成,但是我覺著有必要把今天學到的這個知識點分享一下。
因為,關於這個知識點雖然很簡單,但是卻發現目前網上的一些文章寫的真是不怎麼用心,都是陳述這個問題很好解決,然後文章也附上了實現的程式碼,但是按照作者寫的實現方式本地去執行卻發現是無效的。下麵我來描述下這個問題的場景以及解決方案。
關於AutoSizeableTextView
公司上個版本中有這樣一個需求,要求在一個串列中的每個條目中展示字數不限個數的文字。而且每個條目的寬度都是固定的,展示的文字如果過長,不可以用省略號顯示,只能動態的調整(縮小)文字的字號來達到文字能完全顯示的效果,而且要限一行展示。關於這個效果,其實目前android官方已經提供了實現方式。那就是AutoSizeableTextView。
文章的標題我之所以給AutoSizeableTextView加了雙引號,其實是因為,我們如果只看這個名字,會覺著這應該是android新推出的一個功能更強大的TextView控制元件(起初我也是這樣認為的)。但如果我們點進到原始碼中會發現,其實它是一個介面。
關於這個介面,詳情還請自行閱讀哈。
https://developer.android.com/guide/topics/ui/look-and-feel/autosizing-textview
在Android 8.0,android提供了這樣一個介面用來實現上面我所描述的這個效果。
當然,官方推出這個介面之前,估計已經有很多網上的案例透過自定義View的方式實現了這個效果。
可必須承認的一點是,人家官方提供的東西應該比你自己實現的東西要靠譜些吧(大神請見諒)。雖然這個介面是8.0才提出的,但是為了讓以前的低版本也能實現這個效果,官方提供了相應的相容舉措的,下麵我針對兩種方式進行介紹。
使用
在XML中設定
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" // 加入app名稱空間
android:layout_width="match_parent"
android:layout_height="@dimen/dimen_45">
<android.support.v7.widget.AppCompatTextView
android:layout_width="@dimen/dimen_105"
android:layout_height="@dimen/dimen_32"
android:maxLines="1"
android:textSize="@dimen/dimen_sp_12"
android:textColor="@color/button_r_b_font_color"
app:autoSizeTextType="uniform" // 設定TextView大小設定樣式為支援改變(none時為不支援改變)
app:autoSizeStepGranularity="@dimen/lib_search_dimen_sp_1" // 每次改變的尺寸階梯
app:autoSizeMinTextSize="@dimen/lib_search_dimen_sp_8"
app:autoSizeMaxTextSize="@dimen/lib_search_dimen_sp_12" />
RelativeLayout>
這裡採用AppCompatTextView,它是谷歌為了相容老版本而提供的一個新的類,它實現了AutoSizeableTextView介面, 在xml中透過引入app空間下的對應幾個屬性,就可以實現上述根據控制元件寬度來自適應文字的大小的效果。
在程式碼中動態設定
首先,在佈局中宣告控制元件,註意需要宣告的是AppCompatTextView。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen_45">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/txt_price_section_item"
android:layout_width="@dimen/dimen_105"
android:layout_height="@dimen/dimen_32"
android:background="@drawable/red_black_selector_bg"
android:maxLines="1"
android:textSize="@dimen/dimen_sp_12"
android:textColor="@color/button_r_b_font_color" />
RelativeLayout>
在程式碼中進行改變字號的設定
TextViewCompat.setAutoSizeTextTypeWithDefaults(
textView, TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(
textView, 8, 25, 1, TypedValue.COMPLEX_UNIT_SP);
就這兩行程式碼,首先第一個方式是設定TextView字號支援改變大小樣式。
第二個方法,根據引數的命名我們也能猜出含義,和上面在xml置頂的幾個屬性是一樣的,這裡我不再複述(最後一個引數是尺寸單位)。
這裡需要說明三點,
1、首先為什麼在xml中宣告的控制元件必須是AppCompatTextView。我們點選上面的第二個方法的原始碼中看一下:
public static void setAutoSizeTextTypeUniformWithConfiguration(
@NonNull TextView textView, int autoSizeMinTextSize, int autoSizeMaxTextSize,
int autoSizeStepGranularity, int unit) throws IllegalArgumentException {
if (VERSION.SDK_INT >= 27) {
textView.setAutoSizeTextTypeUniformWithConfiguration(autoSizeMinTextSize, autoSizeMaxTextSize, autoSizeStepGranularity, unit);
} else if (textView instanceof AutoSizeableTextView) {
((AutoSizeableTextView)textView).setAutoSizeTextTypeUniformWithConfiguration(autoSizeMinTextSize, autoSizeMaxTextSize, autoSizeStepGranularity, unit);
}
}
看到了吧,其實是為了相容老版本,如果你的專案不針對27以下的版本進行相容,你完全可以直接在xml中宣告TextView控制元件,而且在xml中也可以直接用android宣告的那幾個屬性進行設定,無須再引入app空間下的屬性。
而當低於27的時候,這個TextView必須屬於AutoSizeableTextView型別的,而前面已經說過,AppCompatTextView實現了AutoSizeableTextView介面,因此,為了相容老版本,我們在xml宣告的時候需要宣告為AppCompatTextView。
小編註:關於第一點,應該是有個前提,如果是繼承自AppCompatActivity,可以直接使用,系統會自動將TextView這個 tag 生成AppCompatTextView實體物件,但是如果是自己做了自定義等操作,一定要繼承AppCompatTextView。
之前也推送給相關原理的文章:
Android兩行程式碼實現換膚從appcompat-v7原理出發https://blog.csdn.net/ximsfei/article/details/54604310
2、其次,要說到一個特別要註意的事情,那就是控制元件的寬度和高度必須要有具體的值,不能設定為wrap_content。這一點估計也好理解,如果寬高不固定,也就不會有根據寬高改變字號這一問題了。
3、最後,關於一行展示這個屬性,平時我們應該都知道兩種方式。那就是singleLine=”true”,或者maxLines=”1″。看我上面的程式碼,兩種方式我都採用的是maxLines=”1″的方式進行設定,如果用singleLine的話會發現無法顯示預期的效果的。
結語
以上,就是使用android官方提供的方法來實現TextView根據寬高自動改變文字大小的方式!一個小知識點,希望能夠對你有幫助哈!