左右对齐的文字效果,很常见,在大多数文章上均可以看到,这种效果能给人带来一种界面整洁的效果,可是若是只是左对齐的话,页面显示就会良莠不齐;而app的页面大多数都是图形+文字的显示效果,左右对齐的文字效果需求仍是很是大的;而反观Android的官方控件TextView并无提供这种左右对齐的显示效果,那么就只能本身来造轮子了;android
这里会涉及到实现原理的解析,若是只是须要使用轮子,请拉到最底下;git
首先,让咱们先来看一下TextView的显示效果: github
原理:将一行剩余的宽度平分给当前单词的间距,这样来达到左右对齐的效果; 那么咱们就有两种实现方案:
(1)TextView绘制一行的计算原理简单粗暴,就是计算这一行显示不下一个单词的时候,就进行回车换行;TextView已经手动给咱们计算出了一行能显示多少的字符,那么咱们只须要经过计算剩余的宽度再进行绘制便可;
会存在问题:若是一行存在单词较少的状况,就会出现间隔过大的问题; 好比: bash
(2)经过手动计算一行能显示多少个字符,而后再计算剩余的宽度进行绘制; 这样只是比第一步多了个本身计算一行能显示多少个字符的操做;
可是这样也会存在问题:若是单词存在中英文混合,或者非中文的状况,会很大几率出现换行时单词被截断的问题; 好比: 微信
以上两种方案都会存在缺陷,那这样的话咱们就得对出现的问题提出解决方案;
当前市场上有成熟的阅读软件,最经常使用的就是左右对齐的排版效果,来看看当前的阅读软件是怎么解决这些问题的; 先看一下微信读书app的显示效果: markdown
再看一下掌阅app的显示效果: app
那么最终方案就是: 经过手动计算一行能显示多少个单词,若是一行最后一个单词显示不下,则进行截断处理,中文则不不存在该问题,这里针对非中文的处理;而后再根据剩余空间进行绘制; 那么有了方案以后,接下来看看具体要怎么实现;oop
(1)先遍历当前页面的字符,将中英文截取为一个个单词,具体实如今getWordList(String text)方法里面;经过遍历当前的字符,判断若是为中文时,则为一个单词,非中文时则经过遍历该英文单词进行拼接,最后拼成一个非中文单词;布局
(2)经过遍历当前的单词,计算每一行要显示的单词集合,具体实如今getLineList(List frontList)这个方法里面;遍历单词时,当添加最后一个单词时,宽度已经超过一行显示的距离,那么就判断最后一个单词是否为中文,是的话则添加到下一行,不然的话则进行截断处理;优化
(3)经过第二步计算出来的每一行的单词,计算剩余的距离进行绘制;
(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之类的;这里只实现了一种规则来进行截断,其余的规则过于复杂,暂时没有引入;
看一下优化后的效果:
喜欢的能够点个star,谢谢!
有更好的想法能够在评论区一块儿讨论!