Canvas的drawText绘制文本自动换行(支持设置显示最大行数)

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();
展开阅读全文

没有更多推荐了,返回首页