From e494e4beb6a124008fd116178cbc38335bd87809 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Tue, 19 Oct 2021 15:47:26 -0700 Subject: [PATCH] Fix onPress event for nested Text in RN Android Summary: This bug is caused by RNAndroid dispatching an incorrect sequence of events to JS when the user taps on a Text. Taking into consideration the example P462662009, when the user taps of the "Inner" text, RN Android is dispatching three events: topTouchStart, topTouchStart and topTouchEnd. The information stored on the first two JS events is correct, but the problem is that it is duplicated. This sequence of events makes Pressability to dispatch the event to the incorrect target. This was originally introduced in D3035589 (https://github.com/facebook/react-native/commit/39fdce259dd46de8fd715efbfd12ede4bc24c8c2) (2016) In this diff I'm changing the way RN Android bubbles events when the user taps on a ReactTextView. From now on, events won't be bubbled anymore, and they will be handled by the ReactRootView.onInterceptTouchEvent: https://fburl.com/code/rbt8$ Additionally, I'm creating a FeatureFlag in case this change has a unknown side effect that's only detected in production. I will create a MC for FB4A in the next diffs of the stack changelog: [Fixed][Android] Fix onPress event for nested Text in RN Android Reviewed By: javache Differential Revision: D31628461 fbshipit-source-id: 177397d4369191a3c97e2f86e801757b27ee5121 --- .../com/facebook/react/config/ReactFeatureFlags.java | 3 +++ .../com/facebook/react/views/text/ReactTextView.java | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index 446ea326ac9..c42be6e1d4e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -105,4 +105,7 @@ public class ReactFeatureFlags { public static boolean useDispatchUniqueForCoalescableEvents = false; public static boolean useUpdatedTouchPreprocessing = false; + + /** TODO: T103427072 Delete ReactFeatureFlags.enableNestedTextOnPressEventFix */ + public static boolean enableNestedTextOnPressEventFix = true; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index a6d48f57d17..5d928bb9a31 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -19,6 +19,7 @@ import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.text.util.Linkify; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import androidx.annotation.Nullable; @@ -31,6 +32,7 @@ import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.ReactConstants; +import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.ReactCompoundView; import com.facebook.react.uimanager.UIManagerModule; @@ -382,6 +384,16 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie return target; } + @Override + public boolean onTouchEvent(MotionEvent ev) { + // The root view always assumes any view that was tapped wants the touch + // and sends the event to JS as such. + // We don't need to do bubbling in native (it's already happening in JS). + // For an explanation of bubbling and capturing, see + // http://javascript.info/tutorial/bubbling-and-capturing#capturing + return ReactFeatureFlags.enableNestedTextOnPressEventFix; + } + @Override protected boolean verifyDrawable(Drawable drawable) { if (mContainsImages && getText() instanceof Spanned) {