Ваши диапазоны так или иначе становятся неизменными, когда текст установлен как выбираемый (TextView#setTextIsSelectable(true)
). Вот хорошая статья о Understanding Spans , которая объясняет изменчивость промежутков. Я также думаю, что этот пост имеет несколько хороших объяснений
Я не уверен, как ваши промежутки становятся неизменными. Может быть, они изменчивы, но просто не отображаются как-то? Непонятно. Может быть, у кого-то есть объяснение этому поведению. Но сейчас есть исправление:
Когда вы поворачиваете устройство или выключаете и снова включаете его, промежутки восстанавливаются или просто применяются повторно. Вот почему вы видите изменения. Исправление состоит в том, чтобы не пытаться изменить пролеты при нажатии, а повторно применить его с жирным шрифтом. Таким образом, изменения вступят в силу. Вам даже не нужно будет звонить invalidate()
. Следите за полужирным промежутком, чтобы его можно было распаковать позже при нажатии на другой промежуток.
Вот результат:
Вот основная деятельность. (Пожалуйста, прости все жесткое кодирование, но это всего лишь пример.)
MainActivity.java
public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private WordSpan mBoldedSpan;
@Override
protected void onCreate(Bundle savedInstanceState) {
Typeface myFont = Typeface.DEFAULT;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.textView);
mTextView.setTextIsSelectable(true);
mTextView.setMovementMethod(createMovementMethod(this));
SpannableString ss = new SpannableString("Hello world! ");
int[][] spanStartEnd = new int[][]{{0, 5}, {6, 12}};
for (int i = 0; i < spanStartEnd.length; i++) {
WordSpan wordSpan = new WordSpan(i, myFont, false) {
@Override
public void onClick(View view) {
// handleWordClick(index, this); // Not sure what this does.
Spannable ss = (Spannable) mTextView.getText();
if (mBoldedSpan != null) {
reapplySpan(ss, mBoldedSpan, false);
}
reapplySpan(ss, this, true);
mBoldedSpan = this;
}
private void reapplySpan(Spannable spannable, WordSpan span, boolean isBold) {
int spanStart = spannable.getSpanStart(span);
int spanEnd = spannable.getSpanEnd(span);
span.setMarking(isBold);
spannable.setSpan(span, spanStart, spanEnd, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
};
ss.setSpan(wordSpan, spanStartEnd[i][0], spanStartEnd[i][1],
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
mTextView.setText(ss, TextView.BufferType.SPANNABLE);
}
// All the other code follows without modification.
}
activity_main.xml
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.04000002"
tools:text="Hello World!" />
</android.support.constraint.ConstraintLayout>
Вот версия, которая использует StyleSpan
. Результаты одинаковы.
MainActivity.java
public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private StyleSpan mBoldedSpan;
@Override
protected void onCreate(Bundle savedInstanceState) {
Typeface myFont = Typeface.DEFAULT;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.textView);
mTextView.setTextIsSelectable(true);
mTextView.setMovementMethod(createMovementMethod(this));
mBoldedSpan = new StyleSpan(android.graphics.Typeface.BOLD);
SpannableString ss = new SpannableString("Hello world!");
int[][] spanStartEnd = new int[][]{{0, 5}, {6, 12}};
for (int i = 0; i < spanStartEnd.length; i++) {
WordSpan wordSpan = new WordSpan(i, myFont, false) {
@Override
public void onClick(View view) {
// handleWordClick(index, this); // Not sure what this does.
Spannable ss = (Spannable) mTextView.getText();
ss.setSpan(mBoldedSpan, ss.getSpanStart(this), ss.getSpanEnd(this),
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
};
ss.setSpan(wordSpan, spanStartEnd[i][0], spanStartEnd[i][1],
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
mTextView.setText(ss, TextView.BufferType.SPANNABLE);
}
// All the other code follows without modification.
}