Согласно официальной документации , если вам нужно обновить ранее добавленный диапазон внутри 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 (), иотображаются пролеты (подъем и верхняя мера не применяются, но, по крайней мере, отображаются).