Fix RTL ScrollView position when content smaller than container (#47280)

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

Noticed in the screenshots of https://github.com/facebook/react-native/pull/47230 that Android's logic of setting scroll content origin to zero, then right aligning scroll offset, won't correctly handle case where content is smaller than scrolling container. We can fix that by only resetting the origin when content overflows container, since we otherwise are not scrollable, and scroll adjustment will not translate.

Changelog:
[Android][Fixed] - Fix RTL ScrollView position when content smaller than container

Reviewed By: rshest

Differential Revision: D65136654

fbshipit-source-id: 2818ff6360cbfac64d7e57bdcbbe8c0a9b4bbb97
This commit is contained in:
Nick Gerleman
2024-10-29 16:29:36 -07:00
committed by Facebook GitHub Bot
parent 0d664100bb
commit 0df59d4f03
2 changed files with 26 additions and 4 deletions
@@ -17,8 +17,11 @@ void AndroidHorizontalScrollContentViewShadowNode::layout(
ConcreteViewShadowNode::layout(layoutContext);
// 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
if (layoutMetrics_.layoutDirection == LayoutDirection::RightToLeft) {
// that extends off the screen to the left so we re-center it to be at most
// zero (where the scrolling offset will be adjusted to match if larger than
// parent width on the Android component side).
if (layoutMetrics_.layoutDirection == LayoutDirection::RightToLeft &&
layoutMetrics_.frame.origin.x < 0) {
layoutMetrics_.frame.origin.x = 0;
}
}
@@ -287,6 +287,19 @@ const examples: Array<RNTesterModuleExample> = [
);
},
},
{
name: 'stubbyHorizontalScrollView',
title: '<ScrollView> (horizontal = true) in RTL not filling content\n',
description:
'A horizontal RTL ScrollView whose content is smaller thatn its containner',
render(): React.Node {
return (
<View testID="stubby-horizontal-rtl-scrollview">
<HorizontalScrollView direction="rtl" itemCount={1} />
</View>
);
},
},
{
title: '<ScrollView> enable & disable\n',
description: 'ScrollView scrolling behaviour can be disabled and enabled',
@@ -541,10 +554,16 @@ const AndroidScrollBarOptions = () => {
);
};
const HorizontalScrollView = (props: {direction: 'ltr' | 'rtl'}) => {
const HorizontalScrollView = (props: {
direction: 'ltr' | 'rtl',
itemCount?: number,
}) => {
const {direction} = props;
const scrollRef = React.useRef<?React.ElementRef<typeof ScrollView>>();
const title = direction === 'ltr' ? 'LTR Layout' : 'RTL Layout';
const items =
props.itemCount == null ? ITEMS : ITEMS.slice(0, props.itemCount);
return (
<View style={{direction}}>
<RNTesterText style={styles.text}>{title}</RNTesterText>
@@ -555,7 +574,7 @@ const HorizontalScrollView = (props: {direction: 'ltr' | 'rtl'}) => {
horizontal={true}
style={[styles.scrollView, styles.horizontalScrollView]}
testID={'scroll_horizontal'}>
{ITEMS.map(createItemRow)}
{items.map(createItemRow)}
</ScrollView>
<Button
label="Scroll to start"