众所周知Android原生的textView在setText()执行之后并不能马上通过getHeight得到当前textView的高度,此时需要使用观察者模式在textView绘制完毕后取得,那么如果需要立即知道此时textView的高度和行数,甚至是要锁定textView的行数并拿到某一行最后一个字符的下标,这时候使用textView就非常的不方便了。如果强行使用观察者模式,在实践中往往需要执行两次setText()不仅会浪费时间,还会让当前的布局闪一下。
那么如果迅速在textView画完之前就拿到textView的高度和某一行最后一个字符,就不能依靠原生的textView了
但是textView是基于一个叫StaticLayout的布局来绘制的,这个布局就有很多android开发者喜闻乐见的api,比如获取高度和某行字符下标什么的。最喜人的是使用这个布局,开发者不需要等到空间绘制完毕之后才能得到绘制的行数和某一行最后一个字符,想象一下如果给某个人一段话和一张纸,让他在不写字的情况下迅速的说出自己这段话究竟能写多少行也是很难的,让他在写之前就告诉你自己在写到某一行的结尾的字符那就更难,而StaticLayout很容易就能做到这一点,而且非常有效率。
另一方面,使用StaticLayout代替textView也是很好的一个选择,StaticLayout本身绘制的速度就要比textView快很多,尤其是在listVIew这种滑动频繁的场景下,StaticLayout拥有更流畅的表现
下面是一个封装了StaticLayout的一个空间,不仅可以实现普通textView的功能,而且能做一些在不绘制的情况下计算行数和字符的方法。
import android.content.Context;
import android.graphics.Canvas;
import android.text.Layout;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class AlxTextView extends View {
TextPaint textPaint = null;
StaticLayout staticLayout = null;
int lineCount = 0;
int width = 720;
int height = 0;
String txt = null;
public AlxTextView(Context context, String content,int width,float textSize) {
super(context);
textPaint = new TextPaint();
textPaint.setAntiAlias(true);
textPaint.setTextSize(textSize);
txt = content;
this.width = width;
staticLayout = new StaticLayout(txt, textPaint, width, Alignment.ALIGN_NORMAL, 1, 0, false);
height = staticLayout.getHeight();
}
public int getLayoutHeight(){
return height;
}
public int getLineCount(){
return staticLayout.getLineCount();
}
@Override
protected void onDraw(Canvas canvas) {
staticLayout.draw(canvas);
super.onDraw(canvas);
}
/**
* 在不绘制textView的情况下算出textView的高度,并且根据最大行数得到应该显示最后一个字符的下标,请在主线程顺序执行,第一个返回值是最后一个字符的下标,第二个返回值是高度
* @param textView
* @param content
* @param width
* @param maxLine
* @return
*/
public static int[] measureTextViewHeight(TextView textView, String content, int width, int maxLine){
Log.i("Alex","宽度是"+width);
TextPaint textPaint = textView.getPaint();
StaticLayout staticLayout = new StaticLayout(content, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
int[] result = new int[2];
if(staticLayout.getLineCount()>maxLine) {//如果行数超出限制
int lastIndex = staticLayout.getLineStart(maxLine) - 1;
result[0] = lastIndex;
result[1] = new StaticLayout(content.substring(0, lastIndex), textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1, 0, false).getHeight();
return result;
}else {//如果行数没有超出限制
result[0] = -1;
result[1] = staticLayout.getHeight();
return result;
}
}
}