两行文本前面加图片用 ImageSpan的实现

先上效果图:

两行文本前面加图片用 ImageSpan的实现_第1张图片
Paste_Image.png

左边应该是个图片,右边就是文本,并且第二行是与图片的左边相对齐的。

这是一个排行榜,总共有10个条目,一开始UI 就给切了1-3三个icon,但是经过考虑以后,这个标题是两行跟一行混排的这种,如果是1行文本的话还好说,但是还有2行的情况必须还要考虑,没办法这种情况下只能让 UI 把1-10的 icon 图片全部切给我们。

一开始做的时候,在文本前面加图片我们一般用 TextView 的 drawableLeft 属性,但是在实际运行展示的话达不到我们要求的效果,在两行文本的时候图片会占据两行,第二行的文本对其的是图片的右边沿。

没办法了只能考虑用 SpannableString 还有ImageSpan 来实现。
具体代码如下:

SpannableString ss = new SpannableString(position +" "+ data.title);
        //得到drawable对象,即所要插入的图片
 Drawable d = context.getResources().getDrawable(ranks[position]);
 d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ss.setSpan(span, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

这个地方要注意 setSpan 里面的0跟1 这两个参数,里面的参数代表的一个是 start 一个是 end 就是在字符串中所占的位置,如果都设置为0,0的话就看不到图片了,再加上图片与文字之间还有空间,这样的话就需要我们手动在要展示的字符串加上任意字符还有加的空格,这就是上图代码中 position +" "+ data.title参数的由来。

这应该是我们常用的设置,但是展示的时候有些问题,因为图片比较大展示的时候相比较在文字的上方,展示要求的话是在图片与文本居中。

首先想到的是 setBounds 方法,里面的参数是设置图片的位置的,手动改变初始的位置改为负值看看能不能是图片向下展示,但是都失败了,个人感觉这个地方最低应该就是以文本的展示的最低点为参考的,就是0 ,0 开始的。
没办法只能上网谷歌了,最终代码如下:

SpannableString ss = new SpannableString(position +" "+ data.title);
        //得到drawable对象,即所要插入的图片
ImageSpan span = new MyIm(context, ranks[position]);
ss.setSpan(span, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
holder.tvTitle.setText(ss);
 
public class MyIm extends ImageSpan
    {
        public MyIm(Context arg0,int arg1) {
            super(arg0, arg1);
        }
        public int getSize(Paint paint, CharSequence text, int start, int end,
                           Paint.FontMetricsInt fm) {
            Drawable d = getDrawable();
            Rect rect = d.getBounds();
            if (fm != null) {
                Paint.FontMetricsInt fmPaint=paint.getFontMetricsInt();
                int fontHeight = fmPaint.bottom - fmPaint.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;
        }

        @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();
            int transY = 0;
            transY = ((bottom-top) - b.getBounds().bottom)/2+top;
            canvas.translate(x, transY);
            b.draw(canvas);
            canvas.restore();
        }
    }

这里要注意,一行文本的话重写 ImageSpan的 draw( )方法就行了,但是两行的话就不行了,还是原先的问题,这样的话就需要再重写getSize( )方法了。

水平有限,如果写的有问题的话请各位大大不吝赐教。

参考文章:
Android ImageSpan与TextView中的text居中对齐问题解决
Android ImageSpan的图文居中对齐

你可能感兴趣的:(两行文本前面加图片用 ImageSpan的实现)