Android 模仿微信讀書(shū)左右對(duì)齊的文字效果

左右對(duì)齊的文字效果,很常見(jiàn),在大多數(shù)文章上都可以看到,這種效果能給人帶來(lái)一種界面整潔的效果,但是如果只是左對(duì)齊的話,頁(yè)面顯示就會(huì)參差不齊;而app的頁(yè)面大多數(shù)都是圖形+文字的顯示效果,左右對(duì)齊的文字效果需求還是非常大的;而反觀Android的官方控件TextView并沒(méi)有提供這種左右對(duì)齊的顯示效果,那么就只能自己來(lái)造輪子了;

這里會(huì)涉及到實(shí)現(xiàn)原理的解析,如果只是需要使用輪子,請(qǐng)拉到最底下;

1. TextView 效果

首先,讓我們先來(lái)看一下TextView的顯示效果:


textView.png

中文情況下還好,但是英文情況下的顯示效果就不是很好看了,右邊會(huì)留了很長(zhǎng)的空白,對(duì)于追求用戶(hù)體驗(yàn)的,這樣的顯示效果肯定是不能滿(mǎn)足的;但是TextView內(nèi)部也沒(méi)有提供API給我們,那么就只能自己來(lái)實(shí)現(xiàn)了;

2. 對(duì)齊原理

原理:將一行剩余的寬度平分給當(dāng)前單詞的間距,這樣來(lái)達(dá)到左右對(duì)齊的效果;
那么我們就有兩種實(shí)現(xiàn)方案:
(1)TextView繪制一行的計(jì)算原理簡(jiǎn)單粗暴,就是計(jì)算這一行顯示不下一個(gè)單詞的時(shí)候,就進(jìn)行回車(chē)換行;TextView已經(jīng)手動(dòng)給我們計(jì)算出了一行能顯示多少的字符,那么我們只需要通過(guò)計(jì)算剩余的寬度再進(jìn)行繪制即可;
會(huì)存在問(wèn)題:如果一行存在單詞較少的情況,就會(huì)出現(xiàn)間隔過(guò)大的問(wèn)題;
比如:

效果1.png

(2)通過(guò)手動(dòng)計(jì)算一行能顯示多少個(gè)字符,然后再計(jì)算剩余的寬度進(jìn)行繪制;
這樣只是比第一步多了個(gè)自己計(jì)算一行能顯示多少個(gè)字符的操作;
但是這樣也會(huì)存在問(wèn)題:如果單詞存在中英文混合,或者非中文的情況,會(huì)很大概率出現(xiàn)換行時(shí)單詞被截?cái)嗟膯?wèn)題;
比如:

效果2.png

3. 最終方案

以上兩種方案都會(huì)存在缺陷,那這樣的話我們就得對(duì)出現(xiàn)的問(wèn)題提出解決方案;
當(dāng)前市場(chǎng)上有成熟的閱讀軟件,最常用的就是左右對(duì)齊的排版效果,來(lái)看看當(dāng)前的閱讀軟件是怎么解決這些問(wèn)題的;
先看一下微信讀書(shū)app的顯示效果:

微信讀書(shū).png

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


掌閱.png

微信讀書(shū)和掌閱都是對(duì)這個(gè)過(guò)長(zhǎng)的單詞進(jìn)行截?cái)嗵幚?,然后使用?”符號(hào)將這兩個(gè)截?cái)嗟膯卧~連接起來(lái),再進(jìn)行繪制時(shí)就不會(huì)出現(xiàn)上述兩種方案的問(wèn)題;

那么最終方案就是:
通過(guò)手動(dòng)計(jì)算一行能顯示多少個(gè)單詞,如果一行最后一個(gè)單詞顯示不下,則進(jìn)行截?cái)嗵幚?,中文則不不存在該問(wèn)題,這里針對(duì)非中文的處理;然后再根據(jù)剩余空間進(jìn)行繪制;
那么有了方案之后,接下來(lái)看看具體要怎么實(shí)現(xiàn);

4. 最終實(shí)現(xiàn)

(1)先遍歷當(dāng)前頁(yè)面的字符,將中英文截取為一個(gè)個(gè)單詞,具體實(shí)現(xiàn)在getWordList(String text)方法里面;通過(guò)遍歷當(dāng)前的字符,判斷如果為中文時(shí),則為一個(gè)單詞,非中文時(shí)則通過(guò)遍歷該英文單詞進(jìn)行拼接,最后拼成一個(gè)非中文單詞;

(2)通過(guò)遍歷當(dāng)前的單詞,計(jì)算每一行要顯示的單詞集合,具體實(shí)現(xiàn)在getLineList(List<String> frontList)這個(gè)方法里面;遍歷單詞時(shí),當(dāng)添加最后一個(gè)單詞時(shí),寬度已經(jīng)超過(guò)一行顯示的距離,那么就判斷最后一個(gè)單詞是否為中文,是的話則添加到下一行,否則的話則進(jìn)行截?cái)嗵幚恚?/p>

(3)通過(guò)第二步計(jì)算出來(lái)的每一行的單詞,計(jì)算剩余的距離進(jìn)行繪制;


具體流程.png

5. 優(yōu)化點(diǎn)

(1)代碼里修改了繪制的邏輯后,那么關(guān)于TextView的一些基礎(chǔ)屬性也要進(jìn)行適配;比如布局的方向,可以使用TextView自帶的屬性來(lái)進(jìn)行設(shè)置;通過(guò)android:gravity=""和android:textAlignment=""屬性來(lái)定義布局的文字方向,是居左還是居右邊,這兩個(gè)屬性都可以進(jìn)行設(shè)置,textAlignment屬性的優(yōu)先級(jí)比較高,如果同時(shí)設(shè)置的話,那么則以textAlignment屬性為準(zhǔn);

<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)對(duì)于實(shí)現(xiàn)的英文單詞截?cái)嗟男Ч€有優(yōu)化的地方,經(jīng)過(guò)一些小伙伴的提醒,發(fā)現(xiàn)還可以通過(guò)音節(jié)的進(jìn)行拆分,再去研究了一波微信讀書(shū)和掌閱的截?cái)嘈Чl(fā)現(xiàn)確實(shí)是使用了音節(jié)來(lái)進(jìn)行截?cái)?,這樣展示效果就更加完美了;

后面研究了一波資料后,發(fā)現(xiàn)可以通過(guò)元音來(lái)進(jìn)行截?cái)?,英語(yǔ)單詞的元音有5個(gè),分別是a,e,i,o,u; 那么就可以通過(guò)元音加一個(gè)輔音的規(guī)則來(lái)進(jìn)行截?cái)啵槐热鏰n,en之類(lèi)的;這里只實(shí)現(xiàn)了一種規(guī)則來(lái)進(jìn)行截?cái)?,其他的?guī)則過(guò)于復(fù)雜,暫時(shí)沒(méi)有引入;

看一下優(yōu)化后的效果:

image

源碼實(shí)現(xiàn)請(qǐng)移步GitHub查看:
github

喜歡的可以點(diǎn)個(gè)star,謝謝!

有更好的想法可以在評(píng)論區(qū)一起討論!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文參加簡(jiǎn)書(shū)七大主題征文活動(dòng),主題:噓,秘密。 “嘿,好久不見(jiàn)。春沉,你比以前漂亮了很多?!崩铍p竹面帶微笑地說(shuō)著客...
    JASON_GGao閱讀 333評(píng)論 0 3
  • 停電了 霓虹不再閃耀 世界暗了下來(lái) 蠟燭和蒲扇 重新找到存在的價(jià)值 工業(yè)區(qū)里是難得的寂靜 高科技也失去了用武之地 ...
    文伴閱讀 208評(píng)論 4 25
  • 請(qǐng)假
    郭苗淼Karine閱讀 166評(píng)論 0 0

友情鏈接更多精彩內(nèi)容