欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

TextView图文混排

程序员文章站 2022-07-23 20:11:42
大家都知道,textView有一个setCompoundDrawables的方法来设置上下左右位置的图标,当然,也可以在xml布局文件中设置,然而问题来了,假如我们把图标放在左边,当我们让TextView分多行显示的时候,会出现一种情况,左边的图标并不会与第一行对齐,而是与整个textView居中对 ......

大家都知道,textview有一个setcompounddrawables的方法来设置上下左右位置的图标,当然,也可以在xml布局文件中设置,然而问题来了,假如我们把图标放在左边,当我们让textview分多行显示的时候,会出现一种情况,左边的图标并不会与第一行对齐,而是与整个textview居中对齐。

即我们要的是下图:

TextView图文混排

结果是这个图:

TextView图文混排

怎么办呢?我们可以用图文混排:

我们可以利用spannablestring和imagespan。

1、构建spannablestring对象。

spannablestring spanstring = new spannablestring(textview.gettext().tostring());

2、获取drawable对象,即将我们的图案转换为drawable对象,并设置大小。

drawable tvdrawable = contextcompat.getdrawable(mcontext, r.drawable.pic);
tvdrawable.setbounds(0, 0, tvdrawable.getminimumwidth(), tvdrawable.getminimumheight());

3、构建imagespan 对象

imagespan span = new imagespan(tvdrawable, imagespan.align_baseline);

 4、设置给上面的spannablestring对象

spanstring.setspan(span, 0, 1, spannable.span_inclusive_exclusive);

5、最终设置给textview

textview.settext(spanstring)

 

加下来讲讲上面的方法:

1、imagespan对象,第二个参数为图像与文字的对齐方式,imagespan只带有两个对齐方式,分别是:align_baseline、align_bottom。

align_bottom 表示与文字内容的底部对齐,如果在构造imagespan时没有传入对齐方式,那么默认就是这种底部对齐。

align_baseline, 表示与文字内容的基线对齐

imagespan span = new imagespan(tvdrawable, imagespan.align_baseline);

2、setspan()方法

public void setspan(object what, int start, int end, int flags) {
        super.setspan(what, start, end, flags);
    }

what传入各种span类型的实例; 
startend标记要替代的文字内容的范围; 
flags是用来标识在span范围内的文本前后输入新的字符时是否把它们也应用这个效果,它有如下几个:

spanned.span_exclusive_exclusive、

spanned.span_inclusive_exclusive、

spanned.span_exclusive_inclusive、

spanned.span_inclusive_inclusive

inclusive表示应用该效果,exclusive表示不应用该效果,如spanned.span_inclusive_exclusive表示对前面的文字应用该效果,而对后面的文字不应用该效果。

 

坑:

1、既然imagespan只带有两个对齐方式,那我们需要自己实现居中对齐:

class myimagespan extends imagespan {

        public static final int align_center = 2;

        public myimagespan(drawable d, int verticalalignment) {
            super(d, verticalalignment);
        }

        @override
        public void draw(canvas canvas, charsequence text, int start, int end, float x, int top, int y, int bottom, paint paint) {
            drawable b = getdrawable();
            canvas.save();

            paint.fontmetricsint fm = paint.getfontmetricsint();

            //系统默认为align_bottom
            int transy = bottom - b.getbounds().bottom;
            if (mverticalalignment == align_baseline) {
                transy -= fm.descent;
            } else {
                transy = ((y + fm.descent + y + fm.ascent) / 2
                        - b.getbounds().bottom / 2);
            }
            canvas.translate(x, transy);
            b.draw(canvas);
            canvas.restore();
        }

        @override
        public int getsize(paint paint, charsequence text, int start, int end, paint.fontmetricsint fm) {
            drawable b = getdrawable();
            rect rect = b.getbounds();
            if (fm != null) {
                paint.fontmetricsint painfm = paint.getfontmetricsint();
                int fontheight = (painfm.bottom - painfm.top);
                int drheight = rect.bottom - rect.top;

                int top = drheight / 2 - fontheight / 4;
                int bottom = drheight / 2 + fontheight / 4;

                fm.ascent = -bottom;
                fm.top = -bottom;
                fm.bottom = top;
                fm.descent = top;
            }
            return rect.right;
        }
    }

 为何上面的自定义能够实现居中对齐呢?首先要了解paint.fontmetrics。

请看另一篇博客:https://www.cnblogs.com/tangzh/p/8692910.html