Canvas的drawText绘制文本自动换行(支持设置显示最大行数)
使用Canvas的drawText绘制文本是不会自动换行的,即使一个很长很长的字符串,drawText也只显示一行,超出部分被隐藏在屏幕之外。可以逐个计算每个字符的宽度,通过一定的算法将字符串分割成多个部分,然后分别调用drawText一部分一部分的显示, 但是这种显示效率会很低。
StaticLayout是android中处理文字换行的一个工具类,StaticLayout已经实现了文本绘制换行处理
StaticLayout的公开的构造函数有三个
7个参数:
public StaticLayout(CharSequence source,
TextPaint paint,
int width,
Layout.Alignment align,
float spacingmult,
float spacingadd,
boolean includepad)
9个参数:
public StaticLayout(CharSequence source,
int bufstart,
int bufend,
TextPaint paint,
int outerwidth,
Layout.Alignment align,
float spacingmult,
float spacingadd,
boolean includepad)
11个参数:
public StaticLayout(CharSequence source,
int bufstart,
int bufend,
TextPaint paint,
int outerwidth,
Layout.Alignment align,
float spacingmult,
float spacingadd,
boolean includepad,
TextUtils.TruncateAt ellipsize,
int ellipsizedWidth)
以11个参数的构造方法为例,各个参数的意义如下:
1.需要分行的字符串 XXXAXXXXBXXX
2.需要分行的字符串从第几的位置开始(如果为A 前面的XXX不显示)
3.需要分行的字符串到哪里结束(如果为B 后面的XXX不显示)
4.画笔对象
5.layout的宽度,字符串超出宽度时自动换行。
6.layout的对其方式,有ALIGN_CENTER, ALIGN_NORMAL, ALIGN_OPPOSITE 三种。
7.相对行间距,相对字体大小,1.5f表示行间距为1.5倍的字体高度。
8.在基础行距上添加多少 实际行间距等于这两者的和。
9.是否包含padding
10.省略位置的模式 TextUtils.TruncateAt.END、TextUtils.TruncateAt.MARQUEE、TextUtils.TruncateAt.MIDDLE、TextUtils.TruncateAt.START 就是android xml 经常写的省略模式如下:
android:ellipsize="end" 省略号在结尾
android:ellipsize="start" 省略号在开头
android:ellipsize="middle" 省略号在中间
android:ellipsize="marquee" 跑马灯
11.超过多少开始省略
通过查看源码,我们知道,11个参数的构造方法调用的是13个参数的构造方法,但是这个方法是@hide 的,我们是没有调用的,外部是无法知道的,但是我们可以通过反射获取,对反射不熟悉的可以参考这一片文章 你必须掌的握反射用法
我们可以看到最后一个参数,可以设置显示的最大行数,默认是Integer.MAX_VALUE
也就是说,利用这个可以设置这个属性
StaticLayout sl = null;
Class clazz = null;
try {
clazz = Class.forName("android.text.StaticLayout");
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
Constructor cons[] = null;
cons = clazz.getConstructors(); //第一步,取得全部构造方法并赋给数组
Constructor con = null;
StaticLayout tmp = null;
try {
//**13个参数 ,注意int.class 不是interge.class**
con = clazz.getConstructor(CharSequence.class, int.class, int.class, TextPaint.class, int.class,
Layout.Alignment.class, TextDirectionHeuristic.class,float.class, float.class,boolean.class,
TextUtils.TruncateAt.class, int.class, int.class);
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
}
try {
tmp = (StaticLayout) con.newInstance(""+e.label, 0, end, mTextPain, (int)sdif - 1, Layout.Alignment.ALIGN_NORMAL, TextDirectionHeuristics.FIRSTSTRONG_LTR, 1.0f, 0.0f, true, TextUtils.TruncateAt.MIDDLE, (int)(sdif - 3 * sradius),2);
} catch (InstantiationException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} catch (InvocationTargetException e1) {
e1.printStackTrace();
}
sl = tmp;
//StaticLayout sl = new StaticLayout(""+e.label, 0, end, mTextPain, (int)sdif - 1, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true, TextUtils.TruncateAt.MIDDLE, (int)(sdif - 3 * sradius));
//从0,0开始绘制
canvas.translate(scx,scy+sradius+paddingTotal);
sl.draw(canvas);
canvas.restore();//调用之前必须canvas.save();