diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 79e57da000f..6eba8f35ba9 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -6959,6 +6959,9 @@ public final class com/facebook/react/views/scroll/ReactHorizontalScrollContaine public static final field Companion Lcom/facebook/react/views/scroll/ReactHorizontalScrollContainerViewManager$Companion; public static final field REACT_CLASS Ljava/lang/String; public fun ()V + public synthetic fun createViewInstance (ILcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/uimanager/ReactStylesDiffMap;Lcom/facebook/react/uimanager/StateWrapper;)Landroid/view/View; + public synthetic fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View; + public fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Lcom/facebook/react/views/view/ReactViewGroup; public fun getName ()Ljava/lang/String; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollContainerLegacyView.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollContainerLegacyView.kt new file mode 100644 index 00000000000..84c7647053a --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollContainerLegacyView.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.views.scroll + +import android.content.Context +import com.facebook.react.modules.i18nmanager.I18nUtil +import com.facebook.react.views.view.ReactViewGroup + +/** + * Used by legacy/Paper renderer to perform offsetting of scroll content when the app-wide layout + * direction is RTL. Contextually set layout direction is not respected by legacy renderer. + */ +internal class ReactHorizontalScrollContainerLegacyView(context: Context) : + ReactViewGroup(context) { + private val isRTL: Boolean = I18nUtil.instance.isRTL(context) + + override fun setRemoveClippedSubviews(removeClippedSubviews: Boolean) { + // removeClippedSubviews logic may read metrics before the offsetting we do in onLayout() and is + // such unsafe + if (isRTL) { + super.setRemoveClippedSubviews(false) + return + } + + super.setRemoveClippedSubviews(removeClippedSubviews) + } + + protected override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + if (isRTL) { + // When the layout direction is RTL, we expect Yoga to give us a layout + // that extends off the screen to the left so we re-center it with left=0 + val newLeft = 0 + val width = right - left + val newRight = newLeft + width + setLeft(newLeft) + setTop(top) + setRight(newRight) + setBottom(bottom) + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollContainerViewManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollContainerViewManager.kt index f1f31d8487a..c9d6c01e065 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollContainerViewManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollContainerViewManager.kt @@ -8,6 +8,12 @@ package com.facebook.react.views.scroll import com.facebook.react.module.annotations.ReactModule +import com.facebook.react.uimanager.ReactStylesDiffMap +import com.facebook.react.uimanager.StateWrapper +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.common.UIManagerType +import com.facebook.react.uimanager.common.ViewUtil +import com.facebook.react.views.view.ReactViewGroup import com.facebook.react.views.view.ReactViewManager /** View manager for {@link ReactHorizontalScrollContainerView} components. */ @@ -15,7 +21,28 @@ import com.facebook.react.views.view.ReactViewManager public class ReactHorizontalScrollContainerViewManager : ReactViewManager() { override public fun getName(): String = REACT_CLASS + protected override fun createViewInstance( + reactTag: Int, + context: ThemedReactContext, + initialProps: ReactStylesDiffMap?, + stateWrapper: StateWrapper? + ): ReactViewGroup { + check(uiManagerType == null) + uiManagerType = ViewUtil.getUIManagerType(reactTag) + val view = super.createViewInstance(reactTag, context, initialProps, stateWrapper) + uiManagerType = null + return view + } + + public override fun createViewInstance(context: ThemedReactContext): ReactViewGroup { + return when (checkNotNull(uiManagerType)) { + UIManagerType.FABRIC -> ReactViewGroup(context) + else -> ReactHorizontalScrollContainerLegacyView(context) + } + } + public companion object { public const val REACT_CLASS: String = "AndroidHorizontalScrollContentView" + private @UIManagerType var uiManagerType: Int? = null } }