ClassCastException fix: getText() returns CharSequence not Spanned.
Summary: ClassCastException fix: getText() returns CharSequence not Spanned. From the other hand, EditTexts getText method returns Editable which extends Spanned. This commit fixes two similar bugs one in flat TextView and another in standard TextView. Also, it removes redundant checks in the ReactEditText. Application without this change sporadically crashes with the following stack trace: ``` java.lang.ClassCastException: java.lang.String cannot be cast to android.text.Spanned at com.facebook.react.views.text.ReactTextView.reactTagForTouch(ReactTextView.java:195) at com.facebook.react.uimanager.TouchTargetHelper.getTouchTargetForView(TouchTargetHelper.java:269) at com.facebook.react.uimanager.TouchTargetHelper.findTargetTagAndCoordinatesForTouch$58866680(TouchTargetHelper.java:101) at com.facebook.react.uimanager.JSTouchDispatcher.handleTouchEvent(JSTouchDispatcher.java:77) at com.facebook.react.ReactRootView.dispatchJSTouchEvent(ReactRootView.java:151) at com.facebook.react.ReactRootView.onInterceptTouchEvent(ReactRootView.java:127) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2110) ``` Closes https://github.com/facebook/react-native/pull/15452 Differential Revision: D6775986 Pulled By: hramos fbshipit-source-id: 6de929937cbbb3e7bd98a708a40700f883cbaef0
This commit is contained in:
parent
f5975a97ad
commit
46cc4907e3
|
@ -70,11 +70,14 @@ import android.text.Spanned;
|
|||
}
|
||||
|
||||
if (mLayout != null) {
|
||||
Spanned text = (Spanned) mLayout.getText();
|
||||
RCTRawText[] spans = text.getSpans(0, text.length(), RCTRawText.class);
|
||||
for (RCTRawText span : spans) {
|
||||
if (span.getReactTag() == tag) {
|
||||
return true;
|
||||
CharSequence text = mLayout.getText();
|
||||
if (text instanceof Spanned) {
|
||||
Spanned spannedText = (Spanned) text;
|
||||
RCTRawText[] spans = spannedText.getSpans(0, text.length(), RCTRawText.class);
|
||||
for (RCTRawText span : spans) {
|
||||
if (span.getReactTag() == tag) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ public class ReactTextView extends TextView implements ReactCompoundView {
|
|||
|
||||
@Override
|
||||
public int reactTagForTouch(float touchX, float touchY) {
|
||||
Spanned text = (Spanned) getText();
|
||||
CharSequence text = getText();
|
||||
int target = getId();
|
||||
|
||||
int x = (int) touchX;
|
||||
|
@ -94,20 +94,21 @@ public class ReactTextView extends TextView implements ReactCompoundView {
|
|||
int lineEndX = (int) layout.getLineRight(line);
|
||||
|
||||
// TODO(5966918): Consider extending touchable area for text spans by some DP constant
|
||||
if (x >= lineStartX && x <= lineEndX) {
|
||||
if (text instanceof Spanned && x >= lineStartX && x <= lineEndX) {
|
||||
Spanned spannedText = (Spanned) text;
|
||||
int index = layout.getOffsetForHorizontal(line, x);
|
||||
|
||||
// We choose the most inner span (shortest) containing character at the given index
|
||||
// if no such span can be found we will send the textview's react id as a touch handler
|
||||
// In case when there are more than one spans with same length we choose the last one
|
||||
// from the spans[] array, since it correspond to the most inner react element
|
||||
ReactTagSpan[] spans = text.getSpans(index, index, ReactTagSpan.class);
|
||||
ReactTagSpan[] spans = spannedText.getSpans(index, index, ReactTagSpan.class);
|
||||
|
||||
if (spans != null) {
|
||||
int targetSpanTextLength = text.length();
|
||||
for (int i = 0; i < spans.length; i++) {
|
||||
int spanStart = text.getSpanStart(spans[i]);
|
||||
int spanEnd = text.getSpanEnd(spans[i]);
|
||||
int spanStart = spannedText.getSpanStart(spans[i]);
|
||||
int spanEnd = spannedText.getSpanEnd(spans[i]);
|
||||
if (spanEnd > index && (spanEnd - spanStart) <= targetSpanTextLength) {
|
||||
target = spans[i].getReactTag();
|
||||
targetSpanTextLength = (spanEnd - spanStart);
|
||||
|
|
|
@ -525,8 +525,8 @@ public class ReactEditText extends EditText {
|
|||
|
||||
@Override
|
||||
protected boolean verifyDrawable(Drawable drawable) {
|
||||
if (mContainsImages && getText() instanceof Spanned) {
|
||||
Spanned text = (Spanned) getText();
|
||||
if (mContainsImages) {
|
||||
Spanned text = getText();
|
||||
TextInlineImageSpan[] spans = text.getSpans(0, text.length(), TextInlineImageSpan.class);
|
||||
for (TextInlineImageSpan span : spans) {
|
||||
if (span.getDrawable() == drawable) {
|
||||
|
@ -539,8 +539,8 @@ public class ReactEditText extends EditText {
|
|||
|
||||
@Override
|
||||
public void invalidateDrawable(Drawable drawable) {
|
||||
if (mContainsImages && getText() instanceof Spanned) {
|
||||
Spanned text = (Spanned) getText();
|
||||
if (mContainsImages) {
|
||||
Spanned text = getText();
|
||||
TextInlineImageSpan[] spans = text.getSpans(0, text.length(), TextInlineImageSpan.class);
|
||||
for (TextInlineImageSpan span : spans) {
|
||||
if (span.getDrawable() == drawable) {
|
||||
|
@ -554,8 +554,8 @@ public class ReactEditText extends EditText {
|
|||
@Override
|
||||
public void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
if (mContainsImages && getText() instanceof Spanned) {
|
||||
Spanned text = (Spanned) getText();
|
||||
if (mContainsImages) {
|
||||
Spanned text = getText();
|
||||
TextInlineImageSpan[] spans = text.getSpans(0, text.length(), TextInlineImageSpan.class);
|
||||
for (TextInlineImageSpan span : spans) {
|
||||
span.onDetachedFromWindow();
|
||||
|
@ -566,8 +566,8 @@ public class ReactEditText extends EditText {
|
|||
@Override
|
||||
public void onStartTemporaryDetach() {
|
||||
super.onStartTemporaryDetach();
|
||||
if (mContainsImages && getText() instanceof Spanned) {
|
||||
Spanned text = (Spanned) getText();
|
||||
if (mContainsImages) {
|
||||
Spanned text = getText();
|
||||
TextInlineImageSpan[] spans = text.getSpans(0, text.length(), TextInlineImageSpan.class);
|
||||
for (TextInlineImageSpan span : spans) {
|
||||
span.onStartTemporaryDetach();
|
||||
|
@ -578,8 +578,8 @@ public class ReactEditText extends EditText {
|
|||
@Override
|
||||
public void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
if (mContainsImages && getText() instanceof Spanned) {
|
||||
Spanned text = (Spanned) getText();
|
||||
if (mContainsImages) {
|
||||
Spanned text = getText();
|
||||
TextInlineImageSpan[] spans = text.getSpans(0, text.length(), TextInlineImageSpan.class);
|
||||
for (TextInlineImageSpan span : spans) {
|
||||
span.onAttachedToWindow();
|
||||
|
@ -590,8 +590,8 @@ public class ReactEditText extends EditText {
|
|||
@Override
|
||||
public void onFinishTemporaryDetach() {
|
||||
super.onFinishTemporaryDetach();
|
||||
if (mContainsImages && getText() instanceof Spanned) {
|
||||
Spanned text = (Spanned) getText();
|
||||
if (mContainsImages) {
|
||||
Spanned text = getText();
|
||||
TextInlineImageSpan[] spans = text.getSpans(0, text.length(), TextInlineImageSpan.class);
|
||||
for (TextInlineImageSpan span : spans) {
|
||||
span.onFinishTemporaryDetach();
|
||||
|
|
Loading…
Reference in New Issue