如何通过drawLeadingMargin在文本末尾添加带样式的引号
问题修复:引用文本尾引号位置错误
错误原因分析
当前代码里尾引号的坐标计算存在两个核心问题:
- Y坐标错误:误用了首行文本的基线坐标,没有匹配到引用文本最后一行的基线,导致换行时尾引号位置跑偏
- X坐标错误:
textSize*text.length()的计算逻辑完全不成立——text是整个TextView的内容,不是当前引用span的范围,而且没有考虑文本排版后的实际宽度和布局方向(比如RTL)
修正方案及代码
修改drawLeadingMargin方法中尾引号的绘制逻辑,替换错误的坐标计算代码:
public class ZMQuoteSpan extends MetricAffectingSpan { // 省略其他代码... @Override public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) { Paint.Style style = p.getStyle(); int color = p.getColor(); boolean isFakeBoldText = p.isFakeBoldText(); Typeface oldTypeface = p.getTypeface(); Typeface typeface = Typeface.create(Typeface.DEFAULT, Typeface.ITALIC); p.setTypeface(typeface); p.setColor(QUOTE_SYSBOLM_COLOR); p.setFakeBoldText(true); // 首引号绘制(保留原有正确逻辑) int spanStart = ((Spanned) text).getSpanStart(this); int spanEnd = ((Spanned) text).getSpanEnd(this); int startY = layout.getLineBaseline(layout.getLineForOffset(spanStart)); c.drawText("\"", x, startY, p); // --- 修正尾引号的坐标计算 --- int endLine = layout.getLineForOffset(spanEnd); int endY = layout.getLineBaseline(endLine); // 获取尾引号所在行的右端X坐标 float endLineRight = layout.getLineLeft(endLine) + layout.getLineWidth(endLine); // 计算引号的X位置:考虑布局方向(dir)和引号自身宽度 float quoteWidth = p.measureText("\""); float quoteX = endLineRight - quoteWidth * dir; c.drawText("\"", quoteX, endY, p); // --------------------------- p.setStyle(style); p.setColor(color); p.setFakeBoldText(isFakeBoldText); p.setTypeface(oldTypeface); } }
关键修正点说明
- 用
spanEnd对应的行基线endY作为尾引号的Y坐标,确保换行时尾引号出现在引用文本的最后一行 - 通过
layout.getLineLeft(endLine)+layout.getLineWidth(endLine)获取引用文本最后一行的实际右端位置 - 用
p.measureText("\"")获取引号自身宽度,结合dir参数处理RTL布局的偏移,保证引号紧贴文本末尾
内容的提问来源于stack exchange,提问作者Text Util
相关产品推荐
相关产品推荐

