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

Android图文混排ImageSpan居中,以及设置间距问题

程序员文章站 2022-05-25 22:13:27
...

Android里面通常使用SpannableString或SpannableStringBuilder来拼接图片与文字,可以将其放到一个TextView控件里面来显示。如果使用过弹幕功能,通常也会使用图文混排的方式去绘制弹幕。

其中会使用ImageSpan来拼接图片,但是系统默认的ImageSpan能力非常弱,默认无法居中对齐,也无法设置图片与文字的间距,所以我们通常需要自定义ImageSpan,来解决上述问题。这里封装了一个工具类CenterSpaceImageSpan来解决这些问题。

一、自定义效果对比

Android图文混排ImageSpan居中,以及设置间距问题

二、自定义ImageSpan

核心逻辑在于getSize的实现,需要加上左右边距,以及绘制时Canvas translate相应的距离


/**
 * 垂直居中ImageSpan,支持margin间距设置
 * <p>
 *
 * @author yinxuming
 * @date 2020/4/2
 */
public class CenterSpaceImageSpan extends ImageSpan {
    private final int mMarginLeft;
    private final int mMarginRight;

    public CenterSpaceImageSpan(Drawable drawable) {
        this(drawable, 0, 0);

    }

    public CenterSpaceImageSpan(Drawable drawable,
                                int marginLeft, int marginRight) {
        super(drawable);
        mMarginLeft = marginLeft;
        mMarginRight = marginRight;
    }

    @Override
    public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x,
                     int top, int y, int bottom,
                     @NonNull Paint paint) {

        Drawable b = getDrawable();
        Paint.FontMetricsInt fm = paint.getFontMetricsInt();
        x = mMarginLeft + x;
        int transY = (y + fm.descent + y + fm.ascent) / 2 - b.getBounds().bottom / 2;
        canvas.save();
        canvas.translate(x, transY);
        b.draw(canvas);
        canvas.restore();
    }

    @Override
    public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable
            Paint.FontMetricsInt fm) {
//        Drawable d = getCachedDrawable();
//        Rect rect = d.getBounds();
//
//        if (fm != null) {
//            fm.ascent = -rect.bottom;
//            fm.descent = 0;
//
//            fm.top = fm.ascent;
//            fm.bottom = 0;
//        }
//
//        return mMarginLeft + rect.right + mMarginRight;
        return mMarginLeft + super.getSize(paint, text, start, end, fm) + mMarginRight;
    }

    private Drawable getCachedDrawable() {
        WeakReference<Drawable> wr = mDrawableRef;
        Drawable d = null;

        if (wr != null) {
            d = wr.get();
        }

        if (d == null) {
            d = getDrawable();
            mDrawableRef = new WeakReference<Drawable>(d);
        }

        return d;
    }

    private WeakReference<Drawable> mDrawableRef;
}

 

三、调用Demo


    private void customSpaceImgSpan() {
        TextView mSpaceImgTv = findViewById(R.id.tv_img_space);
        mSpaceImgTv.setText(buildTvImgSpace(getApplicationContext(),
                "自定义图文混排效果,图片居中,图片左右间距", "100",
                getResources().getDrawable(R.mipmap.ic_launcher)));
    }    


public static CharSequence buildTvImgSpace(Context context, String content, String praiseNumStr,
                                          Drawable mHeadDrawable) {

        BarrageDrawExtEntity mDrawExtEntity = new BarrageDrawExtEntity();
        mDrawExtEntity.configDrawStyle(context, null);

        SpannableStringBuilder ssb = new SpannableStringBuilder();
        Drawable drawable = mHeadDrawable;
        // 1. 头像
        ssb.append(" ");
        drawable.setBounds(0, 0, mDrawExtEntity.mImgSize, mDrawExtEntity.mImgSize);
        ssb.setSpan(new CenterSpaceImageSpan(drawable,  10, 50), 0, 1, ImageSpan.ALIGN_BASELINE);
        // 2. 文本
        ssb.append(content + " " + praiseNumStr);
        TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan(null, 0,
                mDrawExtEntity.mTextSize, ColorStateList.valueOf(mDrawExtEntity.mTextColor), null);
        ssb.setSpan(textAppearanceSpan, 0, ssb.length() - praiseNumStr.length() - 1,
                SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
        // 3. 点赞
        drawable = context.getResources().getDrawable(R.drawable.praise_white);
        drawable.setBounds(0, 0, mDrawExtEntity.mImgSize, mDrawExtEntity.mImgSize);
        ssb.setSpan(new CenterSpaceImageSpan(drawable, 20, 20), ssb.length() - praiseNumStr.length() - 1,
                ssb.length() - praiseNumStr.length(), ImageSpan.ALIGN_BASELINE);
        // 4. 数量
        textAppearanceSpan = new TextAppearanceSpan(null, 0,
                mDrawExtEntity.mTextNumSize, ColorStateList.valueOf(mDrawExtEntity.mTextColor),
                null);
        ssb.setSpan(textAppearanceSpan,
                ssb.length() - praiseNumStr.length(), ssb.length(),
                SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
        return ssb;
    }

 

相关标签: Android