Метод drawplacement замены() не вызывается

Я устанавливаю фон в строке следующим образом:

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() вызывается правильно.

Ответ 1

Если у кого-то есть эта проблема, я столкнулся с ней. Я должен был сделать второй параметр в методе setText(). Мой вызов выглядел как

textView.setText(spanned, TextView.BufferType.SPANNABLE);

Надеюсь, это поможет!

Ответ 2

Похоже, я нашел рабочее (но хакерское) решение этой проблемы. Попробуйте добавить еще один символ в конец строки, чтобы он не был включен в диапазон - и затем вызывается 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);

Похоже, что он игнорирует ширины целых строк.

Ответ 3

В методе getSize() значение Paint.FontMetricsInt fm должно быть пересчитано на основе paint FontMetricsInt:

@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;
}

Ответ 4

Даже если вы вернете ширину диапазона, высота пролета равна 0, когда диапазон охватывает всю строку. Поэтому ваш диапазон на самом деле там, с указанной шириной, но высота равна 0, поэтому не нарисована.

Вы должны установить высоту диапазона, обновляющего значения параметра Paint.FontMetricsInt fm для функции getSize. Проверьте функцию DynamicDrawable.getSize как ссылку на установку высоты, обновив значения FontMetrics.

Ответ 5

Вызовите этот метод просмотра invalidate(), чтобы заставить invoke на draw().

Ответ 6

Я думаю, что это помогает вам. Установить textView ширину соответствия родителя. main_activity.xml

<TextView
   android:width="match_parent"

Ответ 7

Документация для ReplacementSpan.getSize() дает ответ:

Возвращает ширину промежутка. Расширяющие классы могут устанавливать высоту пролета, обновляя атрибуты Paint.FontMetricsInt. Если диапазон охватывает весь текст, а высота не задана, draw() не будет вызываться для диапазона.

Обязательно обновите Paint.FontMetricsInt правильными значениями, чтобы решить проблему.

В моем случае я просто взял метрики из TextView Paint:

@Override
public int getSize(
        Paint paint,
        CharSequence text,
        int start,
        int end,
        Paint.FontMetricsInt fm) {
    final Paint.FontMetrics paintFontMetrics = paint.getFontMetrics();
    if (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;
    }
    //...
}