Android 模仿微信讀書左右對齊的文字效果

左右對齊的文字效果,很常見,在大多數文章上都可以看到,這種效果能給人帶來一種界面整潔的效果,但是如果只是左對齊的話,頁面顯示就會參差不齊;而app的頁面大多數都是圖形+文字的顯示效果,左右對齊的文字效果需求還是非常大的;而反觀Android的官方控件TextView並沒有提供這種左右對齊的顯示效果,那麼就只能自己來造輪子了;

這裏會涉及到實現原理的解析,如果只是需要使用輪子,請拉到最底下;

1. TextView 效果

首先,讓我們先來看一下TextView的顯示效果:

 

textView.png

 

中文情況下還好,但是英文情況下的顯示效果就不是很好看了,右邊會留了很長的空白,對於追求用戶體驗的,這樣的顯示效果肯定是不能滿足的;但是TextView內部也沒有提供API給我們,那麼就只能自己來實現了;

2. 對齊原理

原理:將一行剩餘的寬度平分給當前單詞的間距,這樣來達到左右對齊的效果;
那麼我們就有兩種實現方案:
(1)TextView繪製一行的計算原理簡單粗暴,就是計算這一行顯示不下一個單詞的時候,就進行回車換行;TextView已經手動給我們計算出了一行能顯示多少的字符,那麼我們只需要通過計算剩餘的寬度再進行繪製即可;
會存在問題:如果一行存在單詞較少的情況,就會出現間隔過大的問題;
比如:

效果1.png

 

(2)通過手動計算一行能顯示多少個字符,然後再計算剩餘的寬度進行繪製;
這樣只是比第一步多了個自己計算一行能顯示多少個字符的操作;
但是這樣也會存在問題:如果單詞存在中英文混合,或者非中文的情況,會很大概率出現換行時單詞被截斷的問題;
比如:

效果2.png

 

3. 最終方案

以上兩種方案都會存在缺陷,那這樣的話我們就得對出現的問題提出解決方案;
當前市場上有成熟的閱讀軟件,最常用的就是左右對齊的排版效果,來看看當前的閱讀軟件是怎麼解決這些問題的;
先看一下微信讀書app的顯示效果:

微信讀書.png

 

再看一下掌閱app的顯示效果:

 

掌閱.png

 

微信讀書和掌閱都是對這個過長的單詞進行截斷處理,然後使用“-”符號將這兩個截斷的單詞連接起來,再進行繪製時就不會出現上述兩種方案的問題;

那麼最終方案就是:
通過手動計算一行能顯示多少個單詞,如果一行最後一個單詞顯示不下,則進行截斷處理,中文則不不存在該問題,這裏針對非中文的處理;然後再根據剩餘空間進行繪製;
那麼有了方案之後,接下來看看具體要怎麼實現;

4. 最終實現

(1)先遍歷當前頁面的字符,將中英文截取爲一個個單詞,具體實現在getWordList(String text)方法裏面;通過遍歷當前的字符,判斷如果爲中文時,則爲一個單詞,非中文時則通過遍歷該英文單詞進行拼接,最後拼成一個非中文單詞;

(2)通過遍歷當前的單詞,計算每一行要顯示的單詞集合,具體實現在getLineList(List<String> frontList)這個方法裏面;遍歷單詞時,當添加最後一個單詞時,寬度已經超過一行顯示的距離,那麼就判斷最後一個單詞是否爲中文,是的話則添加到下一行,否則的話則進行截斷處理;

(3)通過第二步計算出來的每一行的單詞,計算剩餘的距離進行繪製;

 

具體流程.png

5. 優化點

(1)代碼裏修改了繪製的邏輯後,那麼關於TextView的一些基礎屬性也要進行適配;比如佈局的方向,可以使用TextView自帶的屬性來進行設置;通過android:gravity=""和android:textAlignment=""屬性來定義佈局的文字方向,是居左還是居右邊,這兩個屬性都可以進行設置,textAlignment屬性的優先級比較高,如果同時設置的話,那麼則以textAlignment屬性爲準;

 

<com.example.testdemo1.XQJustifyTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:textSize="16sp"
        android:gravity="start"
        android:textAlignment="textStart"/>

(2)對於實現的英文單詞截斷的效果,還有優化的地方,經過一些小夥伴的提醒,發現還可以通過音節的進行拆分,再去研究了一波微信讀書和掌閱的截斷效果,發現確實是使用了音節來進行截斷,這樣展示效果就更加完美了;

後面研究了一波資料後,發現可以通過元音來進行截斷,英語單詞的元音有5個,分別是a,e,i,o,u; 那麼就可以通過元音加一個輔音的規則來進行截斷;比如an,en之類的;這裏只實現了一種規則來進行截斷,其他的規則過於複雜,暫時沒有引入;

看一下優化後的效果:

 

image
源碼實現請移步GitHub查看:
github

要是上一個鏈接打不開的話,可以點擊這個

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章