Android 替换span';s draw()方法是';我没打电话
我用字符串设置背景,如下所示:Android 替换span';s draw()方法是';我没打电话,android,spannablestring,Android,Spannablestring,我用字符串设置背景,如下所示: spanString.setSpan(new BackgroundColorSpan(color), 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 但我想在这个背景中增加左和右填充,所以我创建了自定义跨度 public class PaddingBackgroundSpan extends ReplacementSpan { private int mBackgroundColor; private int mForegrou
spanString.setSpan(new BackgroundColorSpan(color), 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
但我想在这个背景中增加左和右填充,所以我创建了自定义跨度
public class PaddingBackgroundSpan extends ReplacementSpan {
private int mBackgroundColor;
private int mForegroundColor;
public PaddingBackgroundSpan(int backgroundColor, int foregroundColor) {
this.mBackgroundColor = backgroundColor;
this.mForegroundColor = foregroundColor;
}
@Override
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
return Math.round(measureText(paint, text, start, end));
}
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
RectF rect = new RectF(x, top, x + measureText(paint, text, start, end), bottom);
paint.setColor(mBackgroundColor);
canvas.drawRect(rect, paint);
paint.setColor(mForegroundColor);
canvas.drawText(text, start, end, x, y, paint);
}
private float measureText(Paint paint, CharSequence text, int start, int end) {
return paint.measureText(text, start, end);
}
我通过以下方式使用我的跨度:
spanString.setSpan(new PaddingBackgroundSpan(color1, color2), 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
不幸的是,没有调用我的draw()方法。getSize()调用正确。调用该视图的
invalidate()
方法,以便强制调用draw()
如果有人遇到此问题,我会遇到它。我要做的是将第二个参数传递到setText()方法中。我的电话看起来像
textView.setText(spanned, TextView.BufferType.SPANNABLE);
希望这有帮助 看来我找到了一个解决这个问题的有效(但不太可靠)方法。尝试在字符串的末尾添加另一个符号,使其不包含在span中,然后调用
draw()
char EXTRA_SPACE = ' ';
String text = originalString + EXTRA_SPACE;
Spannable spannable = new SpannableString(text);
spannable.setSpan(new MyReplacementSpan(), 0, text.length()-1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
textView.setText(spannable);
看起来它忽略了整个字符串宽度的跨距。即使返回跨距的宽度,当跨距覆盖整个字符串时,跨距的高度也为0。因此,跨度实际上在那里,具有指定的宽度,但高度为0,因此未绘制
您必须设置跨度的高度,以更新函数getSize的参数Paint.FontMetricsInt fm的值。检查函数作为参考,通过更新FontMetrics值来设置高度。在方法getSize()
中,必须根据Paint
FontMetricsInt重新计算Paint.FontMetricsInt fm
:
@Override
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
width = Math.round(paint.measureText(text, start, end));
Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
if (fm != null) {
fm.top = metrics.top;
fm.ascent = metrics.ascent;
fm.descent = metrics.descent;
fm.bottom = metrics.bottom;
}
return width;
}
我想这对你有帮助。设置文本视图宽度与父级匹配。
main_activity.xml
<TextView
android:width="match_parent"
的文档提供了以下答案:
返回跨度的宽度。扩展类可以通过更新Paint.FontMetricsInt的属性来设置跨度的高度如果span覆盖整个文本,并且未设置高度,则span将不会调用draw()
确保使用正确的值更新Paint.FontMetricsInt
,以解决问题
在我的例子中,我只是从TextView
的Paint
中获取指标:
@覆盖
公共整数getSize(
油漆,
字符序列文本,
int start,
int end,
Paint.FontMetricsInt格式){
final Paint.FontMetrics paintFontMetrics=Paint.getFontMetrics();
如果(fm!=null){
fm.ascent=(int)paintFontMetrics.ascent;
fm.bottom=(int)paintFontMetrics.bottom;
fm.descent=(int)paintFontMetrics.descent;
fm.leading=(int)paintFontMetrics.leading;
fm.top=(int)paintFontMetrics.top;
}
//...
}
我不想在视图级别上搞得一团糟,我希望Span能够像标准背景色Span那样自行填充。可能吗?我刚刚检查了你的解决方案。在添加SpannableString后调用TextView上的invalidate(这是您的建议吗?),但它不起作用。的确,它起作用了,但为什么我们需要这样的解决方法呢。。