Android中ReplacementSpan背景无法适配文本问题如何解决
问题根因
你当前绘制背景时直接使用系统传入的top、bottom参数,这两个值包含了TextView设置的行间距额外高度,因此背景高度会随行间距同步变化,无法和文字本身的高度适配。
解决方案
不使用系统传入的整行范围参数,改为基于Paint自身的字体度量计算文字实际占用的高度范围绘制背景,完全不受行间距影响,也不会修改原有行高,适配你动态切换Span位置的需求。
修改后的完整代码
public class CoolBackgroundColorSpan extends ReplacementSpan { private final int mBackgroundColor; private final int mTextColor; private final float mCornerRadius; private final float mPaddingStart; private final float mPaddingEnd; private final float mMarginStart; // 新增垂直内边距参数,可根据需求调整也可通过构造方法传入 private final float mVerticalPadding; public CoolBackgroundColorSpan(int mBackgroundColor, int mTextColor, float mCornerRadius, float mPaddingStart, float mPaddingEnd, float mMarginStart, float verticalPadding) { super(); this.mBackgroundColor = mBackgroundColor; this.mTextColor = mTextColor; this.mCornerRadius = mCornerRadius; this.mPaddingStart = mPaddingStart; this.mPaddingEnd = mPaddingEnd; this.mMarginStart = mMarginStart; this.mVerticalPadding = verticalPadding; } @Override public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) { return (int) (mPaddingStart + paint.measureText(text.subSequence(start, end).toString()) + mPaddingEnd); } @Override public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) { float width = paint.measureText(text.subSequence(start, end).toString()); // 基于当前画笔的字体度量计算文字实际上下边界,不受行间距影响 Paint.FontMetrics fm = paint.getFontMetrics(); float textActualTop = y + fm.top; float textActualBottom = y + fm.bottom; // 计算带内边距的背景范围 RectF rect = new RectF( x - mPaddingStart + mMarginStart, textActualTop - mVerticalPadding, x + width + mPaddingEnd + mMarginStart, textActualBottom + mVerticalPadding ); paint.setColor(mBackgroundColor); canvas.drawRoundRect(rect, mCornerRadius, mCornerRadius, paint); paint.setColor(mTextColor); canvas.drawText(text, start, end, x + mMarginStart, y, paint); } }
使用说明
- 新增的
mVerticalPadding参数用于控制背景上下的留白,你可以根据设计需求自定义数值,也可以写死固定值不需要通过构造传入 - 该方案不会修改原有行高,动态切换Span位置时不会出现行高跳动的问题,完全适配卡拉OK滚动高亮的场景
内容的提问来源于stack exchange,提问作者Subith S Y
相关产品推荐
相关产品推荐

