Android 图文一行(富文本展示)效果实现

190 阅读1分钟

最近的需求是要在动态里面加数量不固定标签,类似热门,精品这样子。后续紧跟动态的文本展示在一行内。简单说下实现。

ImageSpan

public ImageSpan(Context context, @DrawableRes int resourceId, int verticalAlignment)

1,Context context:上下文
2,@DrawableRes int resourceId:DrawableResId
3,int verticalAlignment:对齐方式(系统中提供了两种)

DynamicDrawableSpan.ALIGN_BASELINE:以基线对齐
DynamicDrawableSpan.ALIGN_BOTTOM:以底部对齐

ClickableSpan

new ClickableSpan() {
    @Override
    public void onClick(@NonNull View view) {

    }
};

SpannableString

主要是用来添加字符串样式

SpannableString str = new SpannableString(String str);

str.setSpan(imageSpan, j, x, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
public void setSpan(Object what, int start, int end, int flags) {
}

waht:一般为ImageSpan,ClickSpan,StyleSpan等修饰类
start:修饰字符串的开始位置
end:修饰字符串的结束为止(其中占位不包括结束坐标)
flags:

SPAN_INCLUSIVE_EXCLUSIVE: 前包含后不包含                      
SPAN_INCLUSIVE_INCLUSIVE: 前包含后包含  
SPAN_EXCLUSIVE_EXCLUSIVE: 前不包含后不包含  
SPAN_EXCLUSIVE_INCLUSIVE: 前不包含后包含

举例

// 前面加了四个空格
String str = "    我是大帅哥"
SpannableString spanString = new SpannableString(str);
Drawable drawable = getResources().getDrawable(R.drawable.img_hot);
ImageSpan imageSpan = new ImageSpan(this, drawable, ImageSpan.ALIGN_BASELINE);
ClickableSpan clickSpan = new ClickableSpan() {
                        @Override
                        public void onClick(@NonNull View view) {
                            Log.d("Click", "点击了图片");
                        }
                    };
spanString.setSpan(imageSpan, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 可以在相同的位置设置多个效果,在图片上设置点击效果
spanString.setSpan(clickSpan, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

直接设置ImageSpan是无法在文字中垂直居中的,需要自己实现绘制和测量方法。如下:

public class CenterImageSpan extends ImageSpan {
    
    public CenterImageSpan(Drawable drawable, int verticalAlignment) {
        super(drawable, verticalAlignment);
    }
    
    public int getSize(Paint paint, CharSequence text, int start, int end,
                       Paint.FontMetricsInt fm) {
        Drawable drawable = getDrawable();
        Rect rect = drawable.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 drawable = getDrawable();
        Paint.FontMetricsInt fm = paint.getFontMetricsInt();
        int transY = (y + fm.descent + y + fm.ascent) / 2 - drawable.getBounds().bottom / 2;
        canvas.save();
        canvas.translate(x, transY);
        drawable.draw(canvas);
        canvas.restore();
    }
}

其他样式Span后续补充......