Skip to content

Commit ce5eee0

Browse files
jasozhfacebook-github-bot
authored andcommitted
Add TextInput example in ScrollViewExample
Summary: Add a new RNTester example in ScrollViewExample for using the component with TextInputs. This reproduces the issue where TextInputs on Android absorb scroll gestures when textAlign is set to "center" or "right". For TextInputs inside a ScrollView, starting a scroll gesture on the TextInput would not scroll the ScrollView. As this is a common use case, the example acts as a reference to show intended behavior and prevent future regressions. Changelog: [Internal] Differential Revision: D122199421
1 parent 085caf0 commit ce5eee0

1 file changed

Lines changed: 143 additions & 1 deletion

File tree

‎packages/rn-tester/js/examples/ScrollView/ScrollViewExample.js‎

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,22 @@ const examples: Array<RNTesterModuleExample> = [
470470
return <ChildrenWithTouchEventsOverflowingContainerHorizontal />;
471471
},
472472
},
473+
{
474+
title: '<ScrollView> TextInputs\n',
475+
description:
476+
'Vertical scroll gestures on a TextInput should scroll the ScrollView unless the input can also scroll vertically.',
477+
render(): React.Node {
478+
return <VerticalScrollTextInputs />;
479+
},
480+
},
481+
{
482+
title: '<ScrollView> TextInputs (horizontal = true)\n',
483+
description:
484+
'Horizontal scroll gestures on a TextInput should scroll the ScrollView unless the input can also scroll horizontally.',
485+
render(): React.Node {
486+
return <HorizontalScrollTextInputs />;
487+
},
488+
},
473489
];
474490

475491
if (Platform.OS === 'ios') {
@@ -611,6 +627,131 @@ const ScrollsChildToFocusExample = () => {
611627
);
612628
};
613629

630+
const VerticalScrollTextInputs = () => {
631+
const _verticalScrollView =
632+
useRef<?React.ElementRef<typeof ScrollView>>(null);
633+
const [verticalScrolled, setVerticalScrolled] = useState(false);
634+
635+
return (
636+
<View>
637+
<RNTesterText style={styles.text}>
638+
scrolled = {verticalScrolled ? 'true' : 'false'}
639+
</RNTesterText>
640+
<ScrollView
641+
ref={_verticalScrollView}
642+
style={{backgroundColor: '#eeeeee', height: 350}}
643+
contentContainerStyle={{padding: 10, gap: 20}}
644+
nestedScrollEnabled
645+
onScroll={event => {
646+
setVerticalScrolled(event.nativeEvent.contentOffset.y > 0);
647+
}}>
648+
<TextInput placeholder="TextInput" style={styles.textInput} />
649+
<TextInput
650+
placeholder="TextInput (center)"
651+
style={styles.textInput}
652+
textAlign="center"
653+
/>
654+
<TextInput
655+
placeholder="TextInput (right)"
656+
style={styles.textInput}
657+
textAlign="right"
658+
/>
659+
<TextInput
660+
defaultValue={
661+
'A TextInput with a value that overflows the input width so it can be scrolled horizontally.'
662+
}
663+
placeholder="TextInput"
664+
style={styles.textInput}
665+
/>
666+
<TextInput
667+
defaultValue={
668+
'A multiline TextInput\nwith a value that\noverflows the input\nheight so it can be\nscrolled vertically.'
669+
}
670+
placeholder="TextInput"
671+
style={styles.textInput}
672+
multiline
673+
/>
674+
<View
675+
style={[styles.textInput, {backgroundColor: '#cccccc', height: 200}]}
676+
/>
677+
</ScrollView>
678+
<Button
679+
label="Scroll to top"
680+
onPress={() => {
681+
nullthrows<$FlowFixMe>(_verticalScrollView.current).scrollTo({
682+
y: 0,
683+
});
684+
}}
685+
/>
686+
</View>
687+
);
688+
};
689+
690+
const HorizontalScrollTextInputs = () => {
691+
const _horizontalScrollView =
692+
useRef<?React.ElementRef<typeof ScrollView>>(null);
693+
const [horizontalScrolled, setHorizontalScrolled] = useState(false);
694+
695+
return (
696+
<View>
697+
<RNTesterText style={styles.text} testID="horizontal_status">
698+
scrolled = {horizontalScrolled ? 'true' : 'false'}
699+
</RNTesterText>
700+
<ScrollView
701+
ref={_horizontalScrollView}
702+
style={{backgroundColor: '#eeeeee'}}
703+
contentContainerStyle={{padding: 10, gap: 20}}
704+
nestedScrollEnabled
705+
horizontal
706+
onScroll={event => {
707+
setHorizontalScrolled(event.nativeEvent.contentOffset.x > 0);
708+
}}>
709+
<View
710+
style={[
711+
styles.textInput,
712+
{backgroundColor: '#cccccc', width: 100, height: '100%'},
713+
]}
714+
/>
715+
<View style={{gap: 20}}>
716+
<TextInput
717+
placeholder="TextInput"
718+
style={[styles.textInput, {width: 200}]}
719+
/>
720+
<TextInput
721+
defaultValue={
722+
'A TextInput with a value that overflows the input width so it can be scrolled horizontally.'
723+
}
724+
placeholder="TextInput"
725+
style={[styles.textInput, {width: 200}]}
726+
/>
727+
<TextInput
728+
defaultValue={
729+
'A multiline TextInput\nwith a value that\noverflows the input\nheight so it can be\nscrolled vertically.'
730+
}
731+
placeholder="TextInput"
732+
style={[styles.textInput, {width: 200}]}
733+
multiline
734+
/>
735+
</View>
736+
<View
737+
style={[
738+
styles.textInput,
739+
{backgroundColor: '#cccccc', width: 100, height: '100%'},
740+
]}
741+
/>
742+
</ScrollView>
743+
<Button
744+
label="Scroll to start"
745+
onPress={() => {
746+
nullthrows<$FlowFixMe>(_horizontalScrollView.current).scrollTo({
747+
x: 0,
748+
});
749+
}}
750+
/>
751+
</View>
752+
);
753+
};
754+
614755
const HorizontalScrollView = (props: {
615756
direction: 'ltr' | 'rtl',
616757
itemCount?: number,
@@ -1554,8 +1695,9 @@ const styles = StyleSheet.create({
15541695
alignSelf: 'center',
15551696
},
15561697
textInput: {
1557-
height: 40,
1698+
height: 48,
15581699
borderColor: 'gray',
15591700
borderWidth: 1,
1701+
paddingHorizontal: 10,
15601702
},
15611703
});

0 commit comments

Comments
 (0)