這篇博客會講得比較雜:android
- TextView裏各類padding的含義?
- 如何計算每行文字的長度?
- 設置android:maxLines="1"和android:singleLine="true"有什麼區別?
- 爲何設置android:maxLines="1"時TextView的跑馬燈效果就不能正常工做?
雖然咱們平時只用TextView顯示純文本數據,但其實TextView支持設置Background,四周的drawable小圖標,以及Span數據好比文本或圖片。在Android裏不論是什麼控件都是佔據一個矩形的空間,各個矩形之間基本均可以設置padding屬性,這樣一來TextView就被分紅多個矩形區域了,而TextView也提供了獲取各類padding和長度的接口,以下:api
getWidth(), getHeight()
getPaddingLeft/Right/Top/Bottom()
getCompoundPaddingLeft/Right/Top/Bottom()
getExtendedPaddingBottom/Top()
getTotalPaddingLeft/Right/Top/Bottom()佈局
先看一下佈局代碼:學習
@drawable/icon_person_n測試
下面是效果圖,作了一些標註:spa
下面來看一下上述獲取長度的接口的數據,你可使用打日誌方式,我是比較習慣用調試方式:翻譯
因此,總結一下:
getWidth(), getHeight():對應你代碼裏的layout_width和layout_height。3d
getPaddiingLeft/Right/Top/Bottom():對應代碼裏的Padding。
以上兩個比較容易理解,畢竟常常打交道。調試
getCompoundPaddingLeft/Top/Right/Bottom(): 翻譯成中文就是獲取混合的Padding, 既然是混合的,那麼它的值也就是padding + 圖片的大小 + drawablePadding的值。說得通俗點就是,它是獲取文字區域到TextView邊界之間的間隔。附上源碼:日誌
getExtendedPaddingTop():這個是當有部分文字沒有顯示出來時,也就是設置了maxLine時,它的值就等於首行文字到TextView頂端的距離。同理,getExtendedPaddingBottom()就是最後一行文字到TextVeiw底部距離。其餘狀況下,他的值等於getCompoundPaddingTop/Bottom()的值。這個源碼很少,但也不怎麼好講解,就貼兩張圖對比下,就明白了。
getTotalPaddingLeft/Right/Top/Bottom():翻譯下就是獲取總的Padding值,看了下源碼,左右的值直接就是等於compoundPadding的值,上下的值等於ExtendedPadding的值再加上offset的值(跟Gravity的垂直方向的佈局有關。說得通俗點就是,無論有沒有maxLines,上下的值都分別等於首行到TextView頂端和末行到TextView底部的值。
這些接口除了前面兩個比較經常使用外,其餘基本不多用吧,我也是由於在看TextView的跑馬燈部分的源碼才接觸到,而後爲了弄明白才記錄下來的。至於後面那些接口的應用場景,getCompoundPadding()這個的應用場景卻是很明確,能夠用來判斷相應的drawable是否發生點擊事件之類的需求。至於extendedPadding和totalPadding這兩個的應用場景,我想了想,以爲應該是涉及須要計算顯示出來後的文字高度的相關需求時會用到吧。有對這些接口很熟悉的童鞋能夠分享出來哈,一塊兒學習學習。
最後用一張圖總結一下,我把TextView分紅內容區域,內容區域和TextView邊界之間的間隔就是padding的值,內容區域包括drawable區域和文字區域,drawable區域和文字區域之間的間隔就是drawablePadding的值,文字區域和TextView之間的間隔就是CompoundPadding的值。
Q:每行文字的長度不就等於TextView的寬度嗎?直接getWidth()不就行了?
A:再看一下上面那部份內容你就清楚了,只有當TextView寬度設置爲wrap_content,且沒有背景圖或drawable時,文字的長度纔等於getWidth();當文字不多,沒有填充滿時,或是溢出時,文字的長度都得另外計算。
Q:每行文字的長度不同長嗎?
A:由於TextView有本身的換行策略,以下圖所示,顯然每行的文字長度不同長。
Q:文字的長度是指哪段長度?
A:看需求吧,我以爲一般狀況下都是隻須要計算顯示在屏幕上的可見區域的每行文字的長度便可。還有那麼一種需求,當設置了溢出內容用...表示時,那麼其實每行文字的實際長度就不止可見區域那麼長了。
那麼該如何計算文字的長度呢?單單根據上一部分裏的各類Padding值確定不夠,根據各類Padding頂多計算出文字區域的寬度,但實際上每一行文字並不會那麼剛恰好佔滿文字區域的寬度,那麼就還得藉助其餘來進行計算。
方法1:TextView.getPaint().measureText(String text)
但這種方法只是測試傳入的text在該TextView的配置下的總長度,並非計算每一行的長度。
方法2:TextView.getLayout().getLineWidth(int line)
TextView對應的是圖14,正好,利用方法1驗證一下,這個方法計算獲得的是否是每行文字的長度。
徹底正確,因此說這個方法確實計算獲得的是每一行文字的實際長度,注意這裏是實際長度,也就是說當設置singleLine屬性時,用這個方法測量獲得的是一整行文字的長度,包括溢出部分。
官方是推薦說不要再使用singleLine,用maxLines="1"代替。但其實這兩個的效果是不同的,官方api接口裏有說明,都是英文我就不貼圖了,大概翻譯下:
maxLines:限制TextView的最高高度,大概就是指經過限制行數來限制最高高度。
singleLine: 強制設置TextView的文字不換行。
區別就是:maxLines仍是會默認自動進行換行策略,假如一段文字自動換行後有5行,maxLines設置爲1,那麼就只顯示第一行的內容,其餘行不顯示。
可是,若是是設置了singleLine, 那麼這段能夠有5行的文字將會被強制放在1行裏,而後看最多能顯示多少字符,剩下的不顯示。
這樣的區別就是致使了不少人在使用TextVeiw的跑馬燈效果時不能正常工做的狀態,因此下面單獨列出個問題來說。
明白了maxLines="1"和singleLine的區別後,只要再明白跑馬燈的原理,就很容易理解爲何設置成maxLines="1"時跑馬燈不工做了。我在上一篇博客裏寫過跑馬燈啓動的條件,具體的分析能夠去上一篇看,這裏大概說下。
跑馬燈要啓動要同時知足四個條件,其中有一個條件就是這一行的文字長度要大於文字區域的寬度,文字區域的寬度就是TextView的getWidth()扣去ComPoundpaddingLeft再扣去CompoundPaddingRight剩下的長度。 若是是maxLines="1"的話,那麼就像上一問中分析的那樣,全部的文字其實已經被自動換行了,只顯示第一行,而換行是什麼,就是爲了讓每行文字的長度超過文字區域的寬度才進行的換行,也就是說,若是一段文字通過TextView的換行後,那麼每行的文字長度都不會超過文字區域的長度。這樣一來,天然就不知足跑馬燈的啓動條件之一了,跑馬燈也就不能正常工做了。 singleLine的話,則是不會對一段文字進行換行處理,這樣一來,天然就超過了文字區域的長度,因此若是要設置跑馬燈效果的話,只能用singleLine不能用maxLines="1"。 做者:請叫我大蘇 連接:https://www.jianshu.com/p/fd9cce7a333f 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。