ReplacementSpan не работает в Marshmallow
Я добавил текстовый штрих для TextView, используя ReplacementSpan. Он отлично работает в Android Sdk ниже Marshmallow. Но, в зефире он показывает пустой текст. Когда я еще добавил ForegroundSpan в верхнем поле TextView, а затем установить обычай мой пролет под видом его работы. Я не понимаю, я что-нибудь не хватает.
Ниже приведен мой TextSpannable код класса -
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);
2 ответов:
Я придумал, как заставить его работать. Вы должны реализовать
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 } }Если вы также хотите изменить высоту строки, то смотрите этот ответ https://stackoverflow.com/a/39044426/1502079 .
Реализация
LineHeightSpan(согласно ответу вовахоста) не всегда работает правильно. Высота иногда вычисляется неправильно, в результате чего текст вырезается сверху.Возможный обходной путь состоит в том, чтобы
SpannableStringBuilderсодержал что-то еще, а не простоReplacementSpan. К тексту можно добавить пробел нулевой ширины, чтобы он выглядел неизменным, но правильно измерялся и отображался с помощью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);
Comments