Fix keyboard navigation for FlatList with removeClippedSubviews enabled (#50826)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50826

Pull Request resolved: https://github.com/facebook/react-native/pull/50105

Pull Request resolved: https://github.com/facebook/react-native/pull/49543

When using `ReactScrollView` or `ReactHorizontalScrollView` Views with `removeClippedSubviews` keyboard navigation didn't work.

This is because keyboard navigation relies on Android's View hierarchy to find the next focusable element. With `removeClippedSubviews` the next View might've been removed from the hierarchy.

With this change we delegate the job of figuring out the next focusable element to the Shadow Tree, which will always contain layout information of the next element of the ScrollView.

We then prevent the clipping of the topmost parent of the next focusable view to lay out the entire containing element in case we have some necessary context in the parent

Changelog: [Android][Fixed] - Fix keyboard navigation on lists with `removeClippedSubviews` enabled

Reviewed By: NickGerleman

Differential Revision: D73114782

fbshipit-source-id: 081a2216037e033a4638151e5226f430ac093ea5
This commit is contained in:
Jorge Cabiedes Acosta authored and Facebook GitHub Bot committed 2025-04-22 13:17:21 -07:00
1 parent 98c10d568e
commit bbff754db3
7 files changed
+192 -7

No files matched your search

@@ -2343,6 +2343,8 @@ public class com/facebook/react/fabric/FabricUIManager : com/facebook/react/brid
public fun dispatchCommand (IILcom/facebook/react/bridge/ReadableArray;)V
public fun dispatchCommand (IILjava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
public fun dispatchCommand (ILjava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
public fun findNextFocusableElement (III)Ljava/lang/Integer;
public fun findRelativeTopMostParent (II)Ljava/lang/Integer;
public fun getColor (I[Ljava/lang/String;)I
public fun getEventDispatcher ()Lcom/facebook/react/uimanager/events/EventDispatcher;
public fun getPerformanceCounters ()Ljava/util/Map;
@@ -3975,6 +3977,7 @@ public abstract interface class com/facebook/react/uimanager/ReactClippingViewGr
public abstract fun getRemoveClippedSubviews ()Z
public abstract fun setRemoveClippedSubviews (Z)V
public abstract fun updateClippingRect ()V
public abstract fun updateClippingRect (Ljava/util/Set;)V
}
public final class com/facebook/react/uimanager/ReactClippingViewGroupHelper {
@@ -5871,6 +5874,7 @@ public class com/facebook/react/views/scroll/ReactHorizontalScrollView : android
public fun executeKeyEvent (Landroid/view/KeyEvent;)Z
public fun flashScrollIndicators ()V
public fun fling (I)V
public fun focusSearch (Landroid/view/View;I)Landroid/view/View;
public fun getChildVisibleRect (Landroid/view/View;Landroid/graphics/Rect;Landroid/graphics/Point;)Z
public fun getClippingRect (Landroid/graphics/Rect;)V
public fun getFlingAnimator ()Landroid/animation/ValueAnimator;
@@ -5933,6 +5937,7 @@ public class com/facebook/react/views/scroll/ReactHorizontalScrollView : android
public fun setStateWrapper (Lcom/facebook/react/uimanager/StateWrapper;)V
public fun startFlingAnimator (II)V
public fun updateClippingRect ()V
public fun updateClippingRect (Ljava/util/Set;)V
}
public class com/facebook/react/views/scroll/ReactHorizontalScrollViewManager : com/facebook/react/uimanager/ViewGroupManager, com/facebook/react/views/scroll/ReactScrollViewCommandHelper$ScrollCommandHandler {
@@ -5998,6 +6003,7 @@ public class com/facebook/react/views/scroll/ReactScrollView : android/widget/Sc
public fun executeKeyEvent (Landroid/view/KeyEvent;)Z
public fun flashScrollIndicators ()V
public fun fling (I)V
public fun focusSearch (Landroid/view/View;I)Landroid/view/View;
public fun getChildVisibleRect (Landroid/view/View;Landroid/graphics/Rect;Landroid/graphics/Point;)Z
public fun getClippingRect (Landroid/graphics/Rect;)V
public fun getFlingAnimator ()Landroid/animation/ValueAnimator;
@@ -6061,6 +6067,7 @@ public class com/facebook/react/views/scroll/ReactScrollView : android/widget/Sc
public fun setStateWrapper (Lcom/facebook/react/uimanager/StateWrapper;)V
public fun startFlingAnimator (II)V
public fun updateClippingRect ()V
public fun updateClippingRect (Ljava/util/Set;)V
}
public final class com/facebook/react/views/scroll/ReactScrollViewCommandHelper {
@@ -6118,6 +6125,7 @@ public final class com/facebook/react/views/scroll/ReactScrollViewHelper {
public static final fun emitScrollEvent (Landroid/view/ViewGroup;FF)V
public static final fun emitScrollMomentumBeginEvent (Landroid/view/ViewGroup;II)V
public static final fun emitScrollMomentumEndEvent (Landroid/view/ViewGroup;)V
public static final fun findNextFocusableView (Landroid/view/ViewGroup;Landroid/view/View;IZ)Landroid/view/View;
public static final fun forceUpdateState (Landroid/view/ViewGroup;)V
public static final fun getDefaultScrollAnimationDuration (Landroid/content/Context;)I
public static final fun getNextFlingStartValue (Landroid/view/ViewGroup;III)I
@@ -6127,6 +6135,7 @@ public final class com/facebook/react/views/scroll/ReactScrollViewHelper {
public final fun registerFlingAnimator (Landroid/view/ViewGroup;)V
public static final fun removeLayoutChangeListener (Lcom/facebook/react/views/scroll/ReactScrollViewHelper$LayoutChangeListener;)V
public static final fun removeScrollListener (Lcom/facebook/react/views/scroll/ReactScrollViewHelper$ScrollListener;)V
public static final fun resolveAbsoluteDirection (IZI)I
public static final fun smoothScrollTo (Landroid/view/ViewGroup;II)V
public static final fun updateFabricScrollState (Landroid/view/ViewGroup;)V
public final fun updateFabricScrollState (Landroid/view/ViewGroup;II)V
@@ -6926,6 +6935,7 @@ public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGro
public fun setRemoveClippedSubviews (Z)V
public fun setTranslucentBackgroundDrawable (Landroid/graphics/drawable/Drawable;)V
public fun updateClippingRect ()V
public fun updateClippingRect (Ljava/util/Set;)V
public fun updateDrawingOrder ()V
}