Skip to content

Commit caa1fb6

Browse files
fabriziocuccimeta-codesync[bot]
authored andcommitted
Add ImportantForInteractionHelper for interaction handling (#55168)
Summary: Pull Request resolved: #55168 Changelog: [Internal] This diff introduces `ImportantForInteractionHelper`, a helper class that manages the `important_for_interaction` view tag. This tag determines how a view participates in interaction handling based on its `pointerEvents` value. The helper provides a mapping from `PointerEvents` to `important_for_interaction` values: - `AUTO` → `YES` (0x1) - `NONE` → `NO | EXCLUDE_DESCENDANTS` (0x2 | 0x8) - `BOX_ONLY` → `YES | EXCLUDE_DESCENDANTS` (0x1 | 0x8) - `BOX_NONE` → `NO` (0x2) This allows interaction detection systems to understand which views should participate in interaction handling based on their pointer events configuration, which is useful for features like Gaze-based interaction in accessibility and UI harvesting. See design doc: https://docs.google.com/document/d/15Fi47zOHQh--KFWLUxQAUmBENgnZ0ZkYsKyOshPzBAo/edit?tab=t.0#heading=h.61xuoxksjdrp Changes: - Added `ImportantForInteractionHelper.kt` with constants and `setImportantForInteraction()` method - Added `important_for_interaction` tag ID to `ids.xml` - Updated `ReactViewManager.setPointerEvents()` to set the tag when pointer events change - Updated `ReactViewGroup.initView()` to set the default tag value based on initial `PointerEvents.AUTO` - Updated `BaseViewManager.prepareToRecycleView()` to clear the tag when recycling views Reviewed By: javache, mdvacca Differential Revision: D90386675 fbshipit-source-id: f0dab0111f2f5d14d5cb17769578804e2ddcbfe9
1 parent f1bedfb commit caa1fb6

File tree

6 files changed

+76
-0
lines changed

6 files changed

+76
-0
lines changed

packages/react-native/ReactAndroid/api/ReactAndroid.api

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3359,6 +3359,14 @@ public class com/facebook/react/uimanager/IllegalViewOperationException : com/fa
33593359
public final fun getView ()Landroid/view/View;
33603360
}
33613361

3362+
public final class com/facebook/react/uimanager/ImportantForInteractionHelper {
3363+
public static final field IMPORTANT_FOR_INTERACTION_EXCLUDE_DESCENDANTS I
3364+
public static final field IMPORTANT_FOR_INTERACTION_NO I
3365+
public static final field IMPORTANT_FOR_INTERACTION_YES I
3366+
public static final field INSTANCE Lcom/facebook/react/uimanager/ImportantForInteractionHelper;
3367+
public static final fun setImportantForInteraction (Landroid/view/View;Lcom/facebook/react/uimanager/PointerEvents;)V
3368+
}
3369+
33623370
public class com/facebook/react/uimanager/JSPointerDispatcher {
33633371
public fun <init> (Landroid/view/ViewGroup;)V
33643372
public fun handleMotionEvent (Landroid/view/MotionEvent;Lcom/facebook/react/uimanager/events/EventDispatcher;Z)V

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public BaseViewManager(@Nullable ReactApplicationContext reactContext) {
7979
// Reset tags
8080
view.setTag(null);
8181
view.setTag(R.id.pointer_events, null);
82+
view.setTag(R.id.important_for_interaction, null);
8283
view.setTag(R.id.react_test_id, null);
8384
view.setTag(R.id.view_tag_native_id, null);
8485
view.setTag(R.id.labelled_by, null);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.react.uimanager
9+
10+
import android.view.View
11+
import com.facebook.react.R
12+
13+
/**
14+
* Helper class for managing the important_for_interaction view tag. This tag determines how a view
15+
* participates in interaction handling.
16+
*
17+
* The important_for_interaction value is a bitfield that can contain combinations of:
18+
* - [IMPORTANT_FOR_INTERACTION_YES]: The view is important for interaction
19+
* - [IMPORTANT_FOR_INTERACTION_NO]: The view is not important for interaction
20+
* - [IMPORTANT_FOR_INTERACTION_EXCLUDE_DESCENDANTS]: Descendants should be excluded from
21+
* interaction
22+
*/
23+
public object ImportantForInteractionHelper {
24+
/** The view is important for interaction. */
25+
public const val IMPORTANT_FOR_INTERACTION_YES: Int = 0x1
26+
27+
/** The view is not important for interaction. */
28+
public const val IMPORTANT_FOR_INTERACTION_NO: Int = 0x2
29+
30+
/** Descendants of this view should be excluded from interaction handling. */
31+
public const val IMPORTANT_FOR_INTERACTION_EXCLUDE_DESCENDANTS: Int = 0x8
32+
33+
/**
34+
* Sets the important_for_interaction tag on a view based on the given [PointerEvents] value.
35+
*
36+
* The mapping is as follows:
37+
* - [PointerEvents.AUTO] -> [IMPORTANT_FOR_INTERACTION_YES]
38+
* - [PointerEvents.NONE] -> [IMPORTANT_FOR_INTERACTION_NO] |
39+
* [IMPORTANT_FOR_INTERACTION_EXCLUDE_DESCENDANTS]
40+
* - [PointerEvents.BOX_ONLY] -> [IMPORTANT_FOR_INTERACTION_YES] |
41+
* [IMPORTANT_FOR_INTERACTION_EXCLUDE_DESCENDANTS]
42+
* - [PointerEvents.BOX_NONE] -> [IMPORTANT_FOR_INTERACTION_NO]
43+
*
44+
* @param view The view to set the tag on
45+
* @param pointerEvents The pointer events value to convert and set
46+
*/
47+
@JvmStatic
48+
public fun setImportantForInteraction(view: View, pointerEvents: PointerEvents) {
49+
val value =
50+
when (pointerEvents) {
51+
PointerEvents.AUTO -> IMPORTANT_FOR_INTERACTION_YES
52+
PointerEvents.NONE ->
53+
IMPORTANT_FOR_INTERACTION_NO or IMPORTANT_FOR_INTERACTION_EXCLUDE_DESCENDANTS
54+
PointerEvents.BOX_ONLY ->
55+
IMPORTANT_FOR_INTERACTION_YES or IMPORTANT_FOR_INTERACTION_EXCLUDE_DESCENDANTS
56+
PointerEvents.BOX_NONE -> IMPORTANT_FOR_INTERACTION_NO
57+
}
58+
view.setTag(R.id.important_for_interaction, value)
59+
}
60+
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderStyle
4444
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderWidth
4545
import com.facebook.react.uimanager.BackgroundStyleApplicator.setFeedbackUnderlay
4646
import com.facebook.react.uimanager.BlendModeHelper.needsIsolatedLayer
47+
import com.facebook.react.uimanager.ImportantForInteractionHelper
4748
import com.facebook.react.uimanager.LengthPercentage
4849
import com.facebook.react.uimanager.LengthPercentageType
4950
import com.facebook.react.uimanager.MeasureSpecAssertions.assertExplicitMeasureSpec
@@ -176,6 +177,7 @@ public open class ReactViewGroup public constructor(context: Context?) :
176177
hitSlopRect = null
177178
_overflow = Overflow.VISIBLE
178179
pointerEvents = PointerEvents.AUTO
180+
ImportantForInteractionHelper.setImportantForInteraction(this, pointerEvents)
179181
childrenLayoutChangeListener = null
180182
onInterceptTouchEventListener = null
181183
needsOffscreenAlphaCompositing = false

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import com.facebook.react.common.ReactConstants
2121
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
2222
import com.facebook.react.module.annotations.ReactModule
2323
import com.facebook.react.uimanager.BackgroundStyleApplicator
24+
import com.facebook.react.uimanager.ImportantForInteractionHelper
2425
import com.facebook.react.uimanager.LengthPercentage
2526
import com.facebook.react.uimanager.LengthPercentageType
2627
import com.facebook.react.uimanager.PixelUtil.dpToPx
@@ -321,6 +322,7 @@ public open class ReactViewManager : ReactClippingViewManager<ReactViewGroup>()
321322
@ReactProp(name = ViewProps.POINTER_EVENTS)
322323
public open fun setPointerEvents(view: ReactViewGroup, pointerEventsStr: String?) {
323324
view.pointerEvents = PointerEvents.parsePointerEvents(pointerEventsStr)
325+
ImportantForInteractionHelper.setImportantForInteraction(view, view.pointerEvents)
324326
}
325327

326328
@ReactProp(name = "nativeBackgroundAndroid")

packages/react-native/ReactAndroid/src/main/res/views/uimanager/values/ids.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,7 @@
7474

7575
<!-- tag is used to store mixBlendMode effects to apply to the view -->
7676
<item type="id" name="mix_blend_mode"/>
77+
78+
<!-- tag is used to store important_for_interaction state -->
79+
<item type="id" name="important_for_interaction"/>
7780
</resources>

0 commit comments

Comments
 (0)