ReplacementSpan 在 Marshmallow 中不起作用
ReplacementSpan not working in Marshmallow
我使用 ReplacementSpan 为 TextView 添加了文本描边。它在 Marshmallow 下面的 Android Sdk 中运行良好。但是,在棉花糖中它显示空白文本。当我将 ForegroundSpan 添加到 Top TextView,然后将我的自定义跨度设置为下面的视图时,它就可以工作了。我不明白我是否遗漏了什么。
下面是我的 TextSpannable Class 代码 -
public class TextSpannable extends ReplacementSpan {
private final Paint paintFill = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint paintStroke = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Path path = new Path();
private int width;
public TextSpannable(int strokeWidth) {
paintFill.setColor(Color.WHITE);
paintStroke.setStyle(Paint.Style.STROKE);
paintStroke.setStrokeWidth(6);
}
public void setPathEffect(PathEffect effect) {
paintStroke.setPathEffect(effect);
}
@Override
public int getSize(Paint paint, CharSequence text, int start,
int end, Paint.FontMetricsInt fm) {
this.paintFill.setColor(Color.WHITE);
this.paintStroke.setColor(Color.parseColor("#402002"));
width = (int) (paint.measureText(text, start, end) +
this.paintStroke.getStrokeWidth() + paintFill.getTextSize());
return width;
}
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end,
float x, int top, int y,int bottom, Paint paint) {
path.reset();
paint.getTextPath(text.toString(), start, end, x, y, path);
path.close();
canvas.translate(this.paintStroke.getStrokeWidth() / 2, 0);
canvas.drawPath(path,this.paintStroke);
canvas.drawPath(path, this.paintFill);
canvas.translate(-this.paintStroke.getStrokeWidth() / 2, 0);
//canvas.drawText(this.text,start,end,x,y,paintFill);
//canvas.drawText(this.text,start,end,x,y,paintStroke);
}
}
这就是我将其设置为 TextView 的方式 -
spannableString7 =
new SpannableStringBuilder(getString(R.string.string1));
ForegroundColorSpan fcs =new ForegroundColorSpan(Color.TRANSPARENT);
spannableString7.setSpan(fcs,0, getString(R.string.string1).length(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textSpam.setText(spannableString7, TextView.BufferType.SPANNABLE);
//when I comment above block, text becomes blank in Textview
spannableString1 =
new SpannableStringBuilder(getString(R.string.string1));
spannableString1.setSpan(textSpannable,0,getString(R.string.string1).length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString1, TextView.BufferType.SPANNABLE);
我想出了如何让它发挥作用。
您必须实施 LineHeightSpan
因为如果您单独使用 ReplacementSpan
那么我想 TextView
不知道您的文本有多少高度?
只需实施 LineHeightSpan
即可解决问题。
public class CoolBackgroundColorSpan extends ReplacementSpan implements LineHeightSpan {
@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
// Your code here
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
// Your code here
}
@Override
public void chooseHeight(CharSequence charSequence, int i, int i1, int i2, int i3, Paint.FontMetricsInt fontMetricsInt) {
// This method is needed because the class implements LineHeightSpan.
// We don't modify the fontMetricsInt because we don't want to modify the line height.
// The line height will have the height of the text
}
}
如果您还想更改行高,请参阅此答案 。
实施 LineHeightSpan
(根据 vovahost 的回答)并不总是能正常工作。有时高度计算不正确,导致文本在顶部被剪切。
一个可能的解决方法是让 SpannableStringBuilder
包含除 ReplacementSpan
之外的其他内容。可以向文本附加一个零宽度 space,因此它看起来没有变化,但可以通过 TextView
正确测量和显示,例如:
spannableString1 =
new SpannableStringBuilder(getString(R.string.string1));
spannableString1.setSpan(textSpannable,0,getString(R.string.string1).length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString1.append('\u200B'); // <-- append a zero-width space
textView.setText(spannableString1, TextView.BufferType.SPANNABLE);
我使用 ReplacementSpan 为 TextView 添加了文本描边。它在 Marshmallow 下面的 Android Sdk 中运行良好。但是,在棉花糖中它显示空白文本。当我将 ForegroundSpan 添加到 Top TextView,然后将我的自定义跨度设置为下面的视图时,它就可以工作了。我不明白我是否遗漏了什么。
下面是我的 TextSpannable Class 代码 -
public class TextSpannable extends ReplacementSpan {
private final Paint paintFill = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint paintStroke = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Path path = new Path();
private int width;
public TextSpannable(int strokeWidth) {
paintFill.setColor(Color.WHITE);
paintStroke.setStyle(Paint.Style.STROKE);
paintStroke.setStrokeWidth(6);
}
public void setPathEffect(PathEffect effect) {
paintStroke.setPathEffect(effect);
}
@Override
public int getSize(Paint paint, CharSequence text, int start,
int end, Paint.FontMetricsInt fm) {
this.paintFill.setColor(Color.WHITE);
this.paintStroke.setColor(Color.parseColor("#402002"));
width = (int) (paint.measureText(text, start, end) +
this.paintStroke.getStrokeWidth() + paintFill.getTextSize());
return width;
}
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end,
float x, int top, int y,int bottom, Paint paint) {
path.reset();
paint.getTextPath(text.toString(), start, end, x, y, path);
path.close();
canvas.translate(this.paintStroke.getStrokeWidth() / 2, 0);
canvas.drawPath(path,this.paintStroke);
canvas.drawPath(path, this.paintFill);
canvas.translate(-this.paintStroke.getStrokeWidth() / 2, 0);
//canvas.drawText(this.text,start,end,x,y,paintFill);
//canvas.drawText(this.text,start,end,x,y,paintStroke);
}
}
这就是我将其设置为 TextView 的方式 -
spannableString7 =
new SpannableStringBuilder(getString(R.string.string1));
ForegroundColorSpan fcs =new ForegroundColorSpan(Color.TRANSPARENT);
spannableString7.setSpan(fcs,0, getString(R.string.string1).length(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textSpam.setText(spannableString7, TextView.BufferType.SPANNABLE);
//when I comment above block, text becomes blank in Textview
spannableString1 =
new SpannableStringBuilder(getString(R.string.string1));
spannableString1.setSpan(textSpannable,0,getString(R.string.string1).length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString1, TextView.BufferType.SPANNABLE);
我想出了如何让它发挥作用。
您必须实施 LineHeightSpan
因为如果您单独使用 ReplacementSpan
那么我想 TextView
不知道您的文本有多少高度?
只需实施 LineHeightSpan
即可解决问题。
public class CoolBackgroundColorSpan extends ReplacementSpan implements LineHeightSpan {
@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
// Your code here
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
// Your code here
}
@Override
public void chooseHeight(CharSequence charSequence, int i, int i1, int i2, int i3, Paint.FontMetricsInt fontMetricsInt) {
// This method is needed because the class implements LineHeightSpan.
// We don't modify the fontMetricsInt because we don't want to modify the line height.
// The line height will have the height of the text
}
}
如果您还想更改行高,请参阅此答案
实施 LineHeightSpan
(根据 vovahost 的回答)并不总是能正常工作。有时高度计算不正确,导致文本在顶部被剪切。
一个可能的解决方法是让 SpannableStringBuilder
包含除 ReplacementSpan
之外的其他内容。可以向文本附加一个零宽度 space,因此它看起来没有变化,但可以通过 TextView
正确测量和显示,例如:
spannableString1 =
new SpannableStringBuilder(getString(R.string.string1));
spannableString1.setSpan(textSpannable,0,getString(R.string.string1).length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString1.append('\u200B'); // <-- append a zero-width space
textView.setText(spannableString1, TextView.BufferType.SPANNABLE);