Merge "Fix: EditText crash when insert emoji in insert mode" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
4f1352fda8
@@ -37,6 +37,8 @@ import android.view.View;
|
|||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The transformation method used by handwriting insert mode.
|
* The transformation method used by handwriting insert mode.
|
||||||
* This transformation will insert a placeholder string to the original text at the given
|
* This transformation will insert a placeholder string to the original text at the given
|
||||||
@@ -309,26 +311,51 @@ public class InsertModeTransformationMethod implements TransformationMethod, Tex
|
|||||||
return ArrayUtils.emptyArray(type);
|
return ArrayUtils.emptyArray(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
final T[] spansOriginal;
|
T[] spansOriginal = null;
|
||||||
if (mSpannedOriginal != null) {
|
if (mSpannedOriginal != null) {
|
||||||
final int originalStart =
|
final int originalStart =
|
||||||
transformedToOriginal(start, OffsetMapping.MAP_STRATEGY_CURSOR);
|
transformedToOriginal(start, OffsetMapping.MAP_STRATEGY_CURSOR);
|
||||||
final int originalEnd =
|
final int originalEnd =
|
||||||
transformedToOriginal(end, OffsetMapping.MAP_STRATEGY_CURSOR);
|
transformedToOriginal(end, OffsetMapping.MAP_STRATEGY_CURSOR);
|
||||||
|
// We can't simply call SpannedString.getSpans(originalStart, originalEnd) here.
|
||||||
|
// When start == end SpannedString.getSpans returns spans whose spanEnd == start.
|
||||||
|
// For example,
|
||||||
|
// text: abcd span: [1, 3)
|
||||||
|
// getSpan(3, 3) will return the span [1, 3) but getSpan(3, 4) returns no span.
|
||||||
|
//
|
||||||
|
// This creates some special cases when originalStart == originalEnd.
|
||||||
|
// For example:
|
||||||
|
// original text: abcd span1: [1, 3) span2: [3, 4) span3: [3, 3)
|
||||||
|
// transformed text: abc\n\nd span1: [1, 3) span2: [5, 6) span3: [3, 3)
|
||||||
|
// Case 1:
|
||||||
|
// When start = 3 and end = 4, transformedText#getSpan(3, 4) should return span3.
|
||||||
|
// However, because originalStart == originalEnd == 3, originalText#getSpan(3, 3)
|
||||||
|
// returns span1, span2 and span3.
|
||||||
|
//
|
||||||
|
// Case 2:
|
||||||
|
// When start == end == 4, transformedText#getSpan(4, 4) should return nothing.
|
||||||
|
// However, because originalStart == originalEnd == 3, originalText#getSpan(3, 3)
|
||||||
|
// return span1, span2 and span3.
|
||||||
|
//
|
||||||
|
// Case 3:
|
||||||
|
// When start == end == 5, transformedText#getSpan(5, 5) should return span2.
|
||||||
|
// However, because originalStart == originalEnd == 3, originalText#getSpan(3, 3)
|
||||||
|
// return span1, span2 and span3.
|
||||||
|
//
|
||||||
|
// To handle the issue, we need to filter out the invalid spans.
|
||||||
spansOriginal = mSpannedOriginal.getSpans(originalStart, originalEnd, type);
|
spansOriginal = mSpannedOriginal.getSpans(originalStart, originalEnd, type);
|
||||||
} else {
|
spansOriginal = ArrayUtils.filter(spansOriginal,
|
||||||
spansOriginal = null;
|
size -> (T[]) Array.newInstance(type, size),
|
||||||
|
span -> intersect(getSpanStart(span), getSpanEnd(span), start, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
final T[] spansPlaceholder;
|
T[] spansPlaceholder = null;
|
||||||
if (mSpannedPlaceholder != null
|
if (mSpannedPlaceholder != null
|
||||||
&& intersect(start, end, mEnd, mEnd + mPlaceholder.length())) {
|
&& intersect(start, end, mEnd, mEnd + mPlaceholder.length())) {
|
||||||
final int placeholderStart = Math.max(start - mEnd, 0);
|
int placeholderStart = Math.max(start - mEnd, 0);
|
||||||
final int placeholderEnd = Math.min(end - mEnd, mPlaceholder.length());
|
int placeholderEnd = Math.min(end - mEnd, mPlaceholder.length());
|
||||||
spansPlaceholder =
|
spansPlaceholder =
|
||||||
mSpannedPlaceholder.getSpans(placeholderStart, placeholderEnd, type);
|
mSpannedPlaceholder.getSpans(placeholderStart, placeholderEnd, type);
|
||||||
} else {
|
|
||||||
spansPlaceholder = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: sort the spans based on their priority.
|
// TODO: sort the spans based on their priority.
|
||||||
@@ -340,7 +367,10 @@ public class InsertModeTransformationMethod implements TransformationMethod, Tex
|
|||||||
if (mSpannedOriginal != null) {
|
if (mSpannedOriginal != null) {
|
||||||
final int index = mSpannedOriginal.getSpanStart(tag);
|
final int index = mSpannedOriginal.getSpanStart(tag);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
if (index < mEnd) {
|
// When originalSpanStart == originalSpanEnd == mEnd, the span should be
|
||||||
|
// considered "before" the placeholder text. So we return the originalSpanStart.
|
||||||
|
if (index < mEnd
|
||||||
|
|| (index == mEnd && mSpannedOriginal.getSpanEnd(tag) == index)) {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
return index + mPlaceholder.length();
|
return index + mPlaceholder.length();
|
||||||
|
|||||||
@@ -224,6 +224,12 @@ public class InsertModeTransformationMethodTest {
|
|||||||
assertThat(spans0to2.length).isEqualTo(1);
|
assertThat(spans0to2.length).isEqualTo(1);
|
||||||
assertThat(spans0to2[0]).isEqualTo(span1);
|
assertThat(spans0to2[0]).isEqualTo(span1);
|
||||||
|
|
||||||
|
// only span2 is in the range of [3, 4).
|
||||||
|
// note: span1 [0, 3) is not in the range because [3, 4) is not collapsed.
|
||||||
|
final TestSpan[] spans3to4 = transformedText.getSpans(3, 4, TestSpan.class);
|
||||||
|
assertThat(spans3to4.length).isEqualTo(1);
|
||||||
|
assertThat(spans3to4[0]).isEqualTo(span2);
|
||||||
|
|
||||||
// span1 and span2 are in the range of [1, 6).
|
// span1 and span2 are in the range of [1, 6).
|
||||||
final TestSpan[] spans1to6 = transformedText.getSpans(1, 6, TestSpan.class);
|
final TestSpan[] spans1to6 = transformedText.getSpans(1, 6, TestSpan.class);
|
||||||
assertThat(spans1to6.length).isEqualTo(2);
|
assertThat(spans1to6.length).isEqualTo(2);
|
||||||
@@ -262,7 +268,7 @@ public class InsertModeTransformationMethodTest {
|
|||||||
text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
// In the transformedText, the new ranges of the spans are:
|
// In the transformedText "abc\uFFFD def", the new ranges of the spans are:
|
||||||
// span1: [0, 3)
|
// span1: [0, 3)
|
||||||
// span2: [2, 5)
|
// span2: [2, 5)
|
||||||
// span3: [5, 6)
|
// span3: [5, 6)
|
||||||
@@ -277,6 +283,12 @@ public class InsertModeTransformationMethodTest {
|
|||||||
assertThat(spans0to2.length).isEqualTo(1);
|
assertThat(spans0to2.length).isEqualTo(1);
|
||||||
assertThat(spans0to2[0]).isEqualTo(span1);
|
assertThat(spans0to2[0]).isEqualTo(span1);
|
||||||
|
|
||||||
|
// only span2 is in the range of [3, 4).
|
||||||
|
// note: span1 [0, 3) is not in the range because [3, 4) is not collapsed.
|
||||||
|
final TestSpan[] spans3to4 = transformedText.getSpans(3, 4, TestSpan.class);
|
||||||
|
assertThat(spans3to4.length).isEqualTo(1);
|
||||||
|
assertThat(spans3to4[0]).isEqualTo(span2);
|
||||||
|
|
||||||
// span1 and span2 are in the range of [1, 5).
|
// span1 and span2 are in the range of [1, 5).
|
||||||
final TestSpan[] spans1to4 = transformedText.getSpans(1, 4, TestSpan.class);
|
final TestSpan[] spans1to4 = transformedText.getSpans(1, 4, TestSpan.class);
|
||||||
assertThat(spans1to4.length).isEqualTo(2);
|
assertThat(spans1to4.length).isEqualTo(2);
|
||||||
@@ -318,20 +330,143 @@ public class InsertModeTransformationMethodTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void transformedText_getSpanStartAndEnd() {
|
public void transformedText_getSpans_collapsedRange() {
|
||||||
final SpannableString text = new SpannableString(TEXT);
|
final SpannableString text = new SpannableString(TEXT);
|
||||||
final TestSpan span1 = new TestSpan();
|
final TestSpan span1 = new TestSpan();
|
||||||
final TestSpan span2 = new TestSpan();
|
final TestSpan span2 = new TestSpan();
|
||||||
final TestSpan span3 = new TestSpan();
|
final TestSpan span3 = new TestSpan();
|
||||||
|
|
||||||
|
text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
text.setSpan(span2, 3, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
text.setSpan(span3, 3, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
|
// In the transformedText "abc\n\n def", the new ranges of the spans are:
|
||||||
|
// span1: [0, 3)
|
||||||
|
// span2: [3, 3)
|
||||||
|
// span3: [5, 6)
|
||||||
|
final InsertModeTransformationMethod transformationMethod =
|
||||||
|
new InsertModeTransformationMethod(3, false, null);
|
||||||
|
final Spanned transformedText =
|
||||||
|
(Spanned) transformationMethod.getTransformation(text, sView);
|
||||||
|
|
||||||
|
// only span1 is in the range of [0, 0).
|
||||||
|
final TestSpan[] spans0to0 = transformedText.getSpans(0, 0, TestSpan.class);
|
||||||
|
assertThat(spans0to0.length).isEqualTo(1);
|
||||||
|
assertThat(spans0to0[0]).isEqualTo(span1);
|
||||||
|
|
||||||
|
// span1 and span 2 are in the range of [3, 3).
|
||||||
|
final TestSpan[] spans3to3 = transformedText.getSpans(3, 3, TestSpan.class);
|
||||||
|
assertThat(spans3to3.length).isEqualTo(2);
|
||||||
|
assertThat(spans3to3[0]).isEqualTo(span1);
|
||||||
|
assertThat(spans3to3[1]).isEqualTo(span2);
|
||||||
|
|
||||||
|
// only the span2 with collapsed range is in the range of [3, 4).
|
||||||
|
final TestSpan[] spans3to4 = transformedText.getSpans(3, 4, TestSpan.class);
|
||||||
|
assertThat(spans3to4.length).isEqualTo(1);
|
||||||
|
assertThat(spans3to4[0]).isEqualTo(span2);
|
||||||
|
|
||||||
|
// no span is in the range of [4, 5). (span2 is not mistakenly included.)
|
||||||
|
final TestSpan[] spans4to5 = transformedText.getSpans(4, 5, TestSpan.class);
|
||||||
|
assertThat(spans4to5).isEmpty();
|
||||||
|
|
||||||
|
// only span3 is in the range of [4, 6). (span2 is not mistakenly included.)
|
||||||
|
final TestSpan[] spans4to6 = transformedText.getSpans(4, 6, TestSpan.class);
|
||||||
|
assertThat(spans4to6.length).isEqualTo(1);
|
||||||
|
assertThat(spans4to6[0]).isEqualTo(span3);
|
||||||
|
|
||||||
|
// no span is in the range of [4, 4).
|
||||||
|
final TestSpan[] spans4to4 = transformedText.getSpans(4, 4, TestSpan.class);
|
||||||
|
assertThat(spans4to4.length).isEqualTo(0);
|
||||||
|
|
||||||
|
// span3 is in the range of [5, 5).
|
||||||
|
final TestSpan[] spans5to5 = transformedText.getSpans(5, 5, TestSpan.class);
|
||||||
|
assertThat(spans5to5.length).isEqualTo(1);
|
||||||
|
assertThat(spans5to5[0]).isEqualTo(span3);
|
||||||
|
|
||||||
|
// span3 is in the range of [6, 6).
|
||||||
|
final TestSpan[] spans6to6 = transformedText.getSpans(6, 6, TestSpan.class);
|
||||||
|
assertThat(spans6to6.length).isEqualTo(1);
|
||||||
|
assertThat(spans6to6[0]).isEqualTo(span3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void transformedText_getSpans_collapsedRange_singleLine() {
|
||||||
|
final SpannableString text = new SpannableString(TEXT);
|
||||||
|
final TestSpan span1 = new TestSpan();
|
||||||
|
final TestSpan span2 = new TestSpan();
|
||||||
|
final TestSpan span3 = new TestSpan();
|
||||||
|
|
||||||
|
text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
text.setSpan(span2, 3, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
text.setSpan(span3, 3, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
|
// In the transformedText "abc\uFFFD def", the new ranges of the spans are:
|
||||||
|
// span1: [0, 3)
|
||||||
|
// span2: [3, 3)
|
||||||
|
// span3: [4, 5)
|
||||||
|
final InsertModeTransformationMethod transformationMethod =
|
||||||
|
new InsertModeTransformationMethod(3, true, null);
|
||||||
|
final Spanned transformedText =
|
||||||
|
(Spanned) transformationMethod.getTransformation(text, sView);
|
||||||
|
|
||||||
|
// only span1 is in the range of [0, 0).
|
||||||
|
final TestSpan[] spans0to0 = transformedText.getSpans(0, 0, TestSpan.class);
|
||||||
|
assertThat(spans0to0.length).isEqualTo(1);
|
||||||
|
assertThat(spans0to0[0]).isEqualTo(span1);
|
||||||
|
|
||||||
|
// span1 and span2 are in the range of [3, 3).
|
||||||
|
final TestSpan[] spans3to3 = transformedText.getSpans(3, 3, TestSpan.class);
|
||||||
|
assertThat(spans3to3.length).isEqualTo(2);
|
||||||
|
assertThat(spans3to3[0]).isEqualTo(span1);
|
||||||
|
assertThat(spans3to3[1]).isEqualTo(span2);
|
||||||
|
|
||||||
|
// only the span2 with collapsed range is in the range of [3, 4).
|
||||||
|
final TestSpan[] spans3to4 = transformedText.getSpans(3, 4, TestSpan.class);
|
||||||
|
assertThat(spans3to4.length).isEqualTo(1);
|
||||||
|
assertThat(spans3to4[0]).isEqualTo(span2);
|
||||||
|
|
||||||
|
// span3 is in the range of [4, 5). (span2 is not mistakenly included.)
|
||||||
|
final TestSpan[] spans4to5 = transformedText.getSpans(4, 5, TestSpan.class);
|
||||||
|
assertThat(spans4to5.length).isEqualTo(1);
|
||||||
|
assertThat(spans4to5[0]).isEqualTo(span3);
|
||||||
|
|
||||||
|
// only span3 is in the range of [4, 6). (span2 is not mistakenly included.)
|
||||||
|
final TestSpan[] spans4to6 = transformedText.getSpans(4, 6, TestSpan.class);
|
||||||
|
assertThat(spans4to6.length).isEqualTo(1);
|
||||||
|
assertThat(spans4to6[0]).isEqualTo(span3);
|
||||||
|
|
||||||
|
// span3 is in the range of [4, 4).
|
||||||
|
final TestSpan[] spans4to4 = transformedText.getSpans(4, 4, TestSpan.class);
|
||||||
|
assertThat(spans4to4.length).isEqualTo(1);
|
||||||
|
assertThat(spans4to4[0]).isEqualTo(span3);
|
||||||
|
|
||||||
|
// span3 is in the range of [5, 5).
|
||||||
|
final TestSpan[] spans5to5 = transformedText.getSpans(5, 5, TestSpan.class);
|
||||||
|
assertThat(spans5to5.length).isEqualTo(1);
|
||||||
|
assertThat(spans5to5[0]).isEqualTo(span3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void transformedText_getSpanStartAndEnd() {
|
||||||
|
final SpannableString text = new SpannableString(TEXT);
|
||||||
|
final TestSpan span1 = new TestSpan();
|
||||||
|
final TestSpan span2 = new TestSpan();
|
||||||
|
final TestSpan span3 = new TestSpan();
|
||||||
|
final TestSpan span4 = new TestSpan();
|
||||||
|
final TestSpan span5 = new TestSpan();
|
||||||
|
|
||||||
text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
text.setSpan(span4, 3, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
text.setSpan(span5, 3, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
// In the transformedText, the new ranges of the spans are:
|
// In the transformedText, the new ranges of the spans are:
|
||||||
// span1: [0, 3)
|
// span1: [0, 3)
|
||||||
// span2: [2, 6)
|
// span2: [2, 6)
|
||||||
// span3: [6, 7)
|
// span3: [6, 7)
|
||||||
|
// span4: [3, 3)
|
||||||
|
// span5: [5, 6)
|
||||||
final InsertModeTransformationMethod transformationMethod =
|
final InsertModeTransformationMethod transformationMethod =
|
||||||
new InsertModeTransformationMethod(3, false, null);
|
new InsertModeTransformationMethod(3, false, null);
|
||||||
final Spanned transformedText =
|
final Spanned transformedText =
|
||||||
@@ -345,6 +480,12 @@ public class InsertModeTransformationMethodTest {
|
|||||||
|
|
||||||
assertThat(transformedText.getSpanStart(span3)).isEqualTo(6);
|
assertThat(transformedText.getSpanStart(span3)).isEqualTo(6);
|
||||||
assertThat(transformedText.getSpanEnd(span3)).isEqualTo(7);
|
assertThat(transformedText.getSpanEnd(span3)).isEqualTo(7);
|
||||||
|
|
||||||
|
assertThat(transformedText.getSpanStart(span4)).isEqualTo(3);
|
||||||
|
assertThat(transformedText.getSpanEnd(span4)).isEqualTo(3);
|
||||||
|
|
||||||
|
assertThat(transformedText.getSpanStart(span5)).isEqualTo(5);
|
||||||
|
assertThat(transformedText.getSpanEnd(span5)).isEqualTo(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -353,15 +494,21 @@ public class InsertModeTransformationMethodTest {
|
|||||||
final TestSpan span1 = new TestSpan();
|
final TestSpan span1 = new TestSpan();
|
||||||
final TestSpan span2 = new TestSpan();
|
final TestSpan span2 = new TestSpan();
|
||||||
final TestSpan span3 = new TestSpan();
|
final TestSpan span3 = new TestSpan();
|
||||||
|
final TestSpan span4 = new TestSpan();
|
||||||
|
final TestSpan span5 = new TestSpan();
|
||||||
|
|
||||||
text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
text.setSpan(span4, 3, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
text.setSpan(span5, 3, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
// In the transformedText, the new ranges of the spans are:
|
// In the transformedText, the new ranges of the spans are:
|
||||||
// span1: [0, 3)
|
// span1: [0, 3)
|
||||||
// span2: [2, 5)
|
// span2: [2, 5)
|
||||||
// span3: [5, 6)
|
// span3: [5, 6)
|
||||||
|
// span4: [3. 3)
|
||||||
|
// span5: [4, 5)
|
||||||
final InsertModeTransformationMethod transformationMethod =
|
final InsertModeTransformationMethod transformationMethod =
|
||||||
new InsertModeTransformationMethod(3, true, null);
|
new InsertModeTransformationMethod(3, true, null);
|
||||||
final Spanned transformedText =
|
final Spanned transformedText =
|
||||||
@@ -376,6 +523,12 @@ public class InsertModeTransformationMethodTest {
|
|||||||
assertThat(transformedText.getSpanStart(span3)).isEqualTo(5);
|
assertThat(transformedText.getSpanStart(span3)).isEqualTo(5);
|
||||||
assertThat(transformedText.getSpanEnd(span3)).isEqualTo(6);
|
assertThat(transformedText.getSpanEnd(span3)).isEqualTo(6);
|
||||||
|
|
||||||
|
assertThat(transformedText.getSpanStart(span4)).isEqualTo(3);
|
||||||
|
assertThat(transformedText.getSpanEnd(span4)).isEqualTo(3);
|
||||||
|
|
||||||
|
assertThat(transformedText.getSpanStart(span5)).isEqualTo(4);
|
||||||
|
assertThat(transformedText.getSpanEnd(span5)).isEqualTo(5);
|
||||||
|
|
||||||
final ReplacementSpan[] replacementSpans =
|
final ReplacementSpan[] replacementSpans =
|
||||||
transformedText.getSpans(0, 8, ReplacementSpan.class);
|
transformedText.getSpans(0, 8, ReplacementSpan.class);
|
||||||
assertThat(transformedText.getSpanStart(replacementSpans[0])).isEqualTo(3);
|
assertThat(transformedText.getSpanStart(replacementSpans[0])).isEqualTo(3);
|
||||||
|
|||||||
Reference in New Issue
Block a user