requestLayout () для TextView не обновляет промежутки - PullRequest
0 голосов
/ 11 октября 2019

Согласно официальной документации , если вам нужно обновить ранее добавленный диапазон внутри TextView без использования тяжелой процедуры setText (), вы можете сохранить ссылку на диапазон, который вам нужно обновить:

Изменить атрибуты внутреннего диапазона

Если вам нужно изменить только внутренний атрибут изменяемого диапазона, такой как цвет маркера в пользовательском диапазоне маркеров,Вы можете избежать накладных расходов от вызова setText () несколько раз, сохраняя ссылку на промежуток при его создании. Когда вам нужно изменить диапазон, вы можете изменить ссылку и затем вызвать invalidate () или requestLayout () в TextView, в зависимости от типа атрибута, который вы изменили.

В приведенном ниже примере кодаПользовательская реализация маркированной точки имеет красный цвет по умолчанию, который при нажатии кнопки меняется на серый:

public class MainActivity extends AppCompatActivity {

    private BulletPointSpan bulletSpan = new BulletPointSpan(Color.RED);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        SpannableString spannable = new SpannableString("Text is spantastic");
        // setting the span to the bulletSpan field
        spannable.setSpan(bulletSpan, 0, 4, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
        styledText.setText(spannable);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // change the color of our mutable span
                bulletSpan.setColor(Color.GRAY);
                // color won’t be changed until invalidate is called
                styledText.invalidate();
            }
        });
    }
}

Поэтому, чтобы повторить это, я прикрепляю DrawableSpan к включаемому тексту, который я передаю в TextView. , а затем я обновлю этот промежуток позже, когда мой чертеж будет готов (получен из отдаленного места). Проблема в том, что мой вызов requestLayout () не обновляет только что обновленный диапазон, .

 DrawableSpan span = new DrawableSpan();
 text.setSpan(span, i1, i2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
 textView.setText(text, TextView.BufferType.SPANNABLE);
 mRequestManager.load(source).into(new SimpleTarget<Drawable>() {
                    @Override
                    public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                        span.setDrawable(resource);
                        textView.requestLayout();
                    }
                });

Вот DrawableSpan, который я использую, это точная копия вставки фреймворка DynamicDrawableSpan , который является суперклассом ImageSpan (который обеспечивает перегрузки для загрузки drawalbe из различных входов). Я должен был создать свой собственный диапазон, чтобы позволить мне позже установить рисование.

public class DrawableSpan extends ReplacementSpan {

    private static final String TAG = "DynamicDrawableSpan";

    /**
     * A constant indicating that the bottom of this span should be aligned
     * with the bottom of the surrounding text, i.e., at the same level as the
     * lowest descender in the text.
     */
    public static final int ALIGN_BOTTOM = 0;

    /**
     * A constant indicating that the bottom of this span should be aligned
     * with the baseline of the surrounding text.
     */
    public static final int ALIGN_BASELINE = 1;

    private final int mVerticalAlignment;
    private Drawable mDrawable;

    public DrawableSpan() {
        this(null);
    }

    public DrawableSpan(Drawable drawable) {
        this(drawable, ALIGN_BOTTOM);
    }

    public DrawableSpan(Drawable drawable, int verticalAlignment) {
        setDrawable(drawable);
        mVerticalAlignment = verticalAlignment;
    }

    public void setDrawable(Drawable drawable) {
        if (drawable == null) return;
        mDrawable = drawable;
        mDrawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    }

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end,
                       Paint.FontMetricsInt fm) {
        if (mDrawable == null) return 0;
        Rect rect = mDrawable.getBounds();
        if (fm != null) {
            fm.ascent = -rect.bottom;
            fm.descent = 0;
            fm.top = fm.ascent;
            fm.bottom = 0;
        }
        return rect.right;
    }

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x,
                     int top, int y, int bottom, Paint paint) {

        if (mDrawable == null) return;

        canvas.save();
        int transY = bottom - mDrawable.getBounds().bottom;
        if (mVerticalAlignment == ALIGN_BASELINE) {
            transY -= paint.getFontMetricsInt().descent;
        }
        canvas.translate(x, transY);
        mDrawable.draw(canvas);
        canvas.restore();
    }

}

Самое странное, что, если я блокирую и разблокирую устройство, вызываются методы getSize () и draw (), иотображаются пролеты (подъем и верхняя мера не применяются, но, по крайней мере, отображаются).

...