如下图所示,当你在第二行将要输入“好”时,因为你输入"好"后该行文本宽度已经大于此时EditText的宽度了,所以“好”字会被认为是重启一行,这样你得到的每行文本就是错的了,因为“好”应该显示在第二行才对。
这就涉及到我在思路探究中提到的第一个问题,无论我字体怎么缩小放大,如何保证每行最多可显示的文本都是一样的?
那么如何保证呢?
其实很简单,因为影响到文字自动换行的因素主要就是字体大小和最大文本宽度,那么只要保证这两个因素不变,无论你输入什么文本,都能准确一致的拆分出每一行的文字。
因为EditText的每行字体在变,而且宽度也在变,所以通过EditText自带的Layout算出的每行文本肯定是错误的。
所以,思路应该是这样的,你需要构建一个用于计算的Layout,这个Layout的字体大小和宽度必须是固定不变的,这样它就能够保证每行最多可容纳的文本始终是一样的,这样我就能够准确拆分出每行文本。
前面已经说过EditText的计算工作都是交给DynamicLayout,所以我们需要创建的是DynamicLayout。代码如下
protected Layout buildCalculateLayout(CharSequence text,TextView host){
TextPaint paint = new TextPaint(host.getPaint());
paint.setTextSize(mDefFontSize);
return new DynamicLayout(text,paint, mDefMaxTextWidth,host.getLayout().getAlignment(),host.getLayout().getSpacingMultiplier(),host.getLayout().getSpacingAdd(),host.getIncludeFontPadding());
}
需要注意的是,这里除了字体大小和宽度,其他的参数都需要跟EditText的参数一样。
其中mDefFontSize是一开始定义的一个默认字体大小,mDefMaxTextWidth是EditText在没动态调整宽度前的宽度(需要减去padding)。
这样子每次都是通过自构建的Layout去计算每行的文本,就不需要考虑EditText的字体和宽度的动态变化。
二.按匹配最大宽度计算每行字体大小
搞定了第一步拆行后,其实已经离成功不远了,接下来就是如何确定每行字体大小了。
确定字体大小说简单简单,说难也难,关键是看你有没有想到那个点。比如一开始我一直纠结于每行文字是怎么随着输入文字个数和行数变化动态改变的,陷入了局部细节,搞得自己晕头转向,如果按照这个方向思考我感觉估计是怎么做都搞不定的。
后来,想了两天后还是没搞明白,我就试着换个思维方式,从整体来考虑,接下来就有种恍然大悟的感觉,原来其实没那么难。
首先,有一个规律是很显然的:
每行文字越多,它的字体就越小,文字越少,字体就越大。
那么我就想一开始时你把每行文字的宽度放大到最大文本宽度,算出匹配这个宽度的字体应该多大,这样文字越少的行,字体就越大,文字越多的行,字体就越小,这个不就是符合那个规律吗。