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

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

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

一、自定义效果对比

Android图文混排ImageSpan居中,以及设置间距问题_第1张图片

二、自定义ImageSpan

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


/**
 * 垂直居中ImageSpan,支持margin间距设置
 * 

* * @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 wr = mDrawableRef; Drawable d = null; if (wr != null) { d = wr.get(); } if (d == null) { d = getDrawable(); mDrawableRef = new WeakReference(d); } return d; } private WeakReference 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,图文混排,弹幕,ImageSpan居中,ImageSpan间距)