我如何在 React Native 中嵌套水平 ScrollView?
How can I have nested horizontal ScrollViews in React Native?
我从 React Native Nested ScrollView Can`t Scroll on Android Device
看到 React Native 提供了嵌套的垂直滚动视图
问题是它似乎不适用于 Android 上的嵌套水平滚动视图。有关示例,请参见此代码:
https://snack.expo.io/@harrytravelchime/broken-horizontal-scroll
import React from 'react';
import _ from 'lodash';
import { View, ScrollView, StyleSheet, Text, SafeAreaView } from 'react-native';
export default class App extends React.PureComponent {
render() {
return (
<SafeAreaView style={styles.container}>
<ScrollView
style={{ height: '100%', width: '100%' }}
horizontal
nestedScrollEnabled
>
<View style={{ flexDirection: 'row' }}>
<ScrollView
style={{ width: 200, height: '100%' }}
horizontal
nestedScrollEnabled
>
<View style={{ flexDirection: 'row' }}>
{_.times(200, n => (
<View key={1000 + n} style={{ marginRight: 10 }}>
<Text>{1000 + n}</Text>
</View>
))}
</View>
</ScrollView>
{_.times(200, n => (
<View key={n} style={{ marginRight: 10 }}>
<Text>{n}</Text>
</View>
))}
</View>
</ScrollView>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'stretch',
paddingVertical: 50,
},
});
另一方面,除了垂直滚动之外,相同的代码完全有效:
https://snack.expo.io/@harrytravelchime/working-vertical-scroll
有没有办法使嵌套水平滚动起作用?
我想出的一个解决方案是 TouchableWithoutFeedback
跟踪用户在内部 ScrollView 中的任何触摸。一旦检测到触摸,它就会禁用外部 ScrollView 上的滚动,这会导致内部 ScrollView 接收事件。
以上代码的主要变化是:
- 添加状态
outerScrollViewScrollEnabled
- 当通过
TouchableWithoutFeedback
触摸内部 ScrollView 时,更改该状态
- 使外部 ScrollView 的
scrollEnabled
依赖于它
import React from "react";
import _ from "lodash";
import {
View,
ScrollView,
StyleSheet,
Text,
SafeAreaView,
TouchableWithoutFeedback
} from "react-native";
interface State {
outerScrollViewScrollEnabled: boolean;
}
export default class App extends React.PureComponent {
state = { outerScrollViewScrollEnabled: true };
handleInnerPressIn = () => this.setState({ outerScrollViewScrollEnabled: false });
handleInnerPressOut = () => this.setState({ outerScrollViewScrollEnabled: true });
render() {
const { outerScrollViewScrollEnabled } = this.state;
return (
<SafeAreaView style={styles.container}>
<ScrollView
style={{ height: "100%", width: "100%" }}
horizontal
scrollEnabled={outerScrollViewScrollEnabled}
>
<View style={{ flexDirection: "row" }}>
<ScrollView style={{ width: 200, height: "100%" }} horizontal>
<TouchableWithoutFeedback
onPressIn={this.handleInnerPressIn}
onPressOut={this.handleInnerPressOut}
>
<View style={{ flexDirection: "row" }}>
{_.times(200, n => (
<View key={1000 + n} style={{ marginRight: 10 }}>
<Text>{1000 + n}</Text>
</View>
))}
</View>
</TouchableWithoutFeedback>
</ScrollView>
{_.times(200, n => (
<View key={n} style={{ marginRight: 10 }}>
<Text>{n}</Text>
</View>
))}
</View>
</ScrollView>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
justifyContent: "center",
alignItems: "stretch",
paddingVertical: 50
}
});
如果您使用的是 react-native-gesture-handler,还有一种更简单的解决方案
import { ScrollView } from 'react-native'
import { ScrollView as GestureHandlerScrollView } from 'react-native-gesture-handler'
<ScrollView horizontal>
<GestureHandlerScrollView horizontal />
</ScrollVIew>
我从 react-native 那里得到了这个答案 github issue
我从 React Native Nested ScrollView Can`t Scroll on Android Device
看到 React Native 提供了嵌套的垂直滚动视图问题是它似乎不适用于 Android 上的嵌套水平滚动视图。有关示例,请参见此代码:
https://snack.expo.io/@harrytravelchime/broken-horizontal-scroll
import React from 'react';
import _ from 'lodash';
import { View, ScrollView, StyleSheet, Text, SafeAreaView } from 'react-native';
export default class App extends React.PureComponent {
render() {
return (
<SafeAreaView style={styles.container}>
<ScrollView
style={{ height: '100%', width: '100%' }}
horizontal
nestedScrollEnabled
>
<View style={{ flexDirection: 'row' }}>
<ScrollView
style={{ width: 200, height: '100%' }}
horizontal
nestedScrollEnabled
>
<View style={{ flexDirection: 'row' }}>
{_.times(200, n => (
<View key={1000 + n} style={{ marginRight: 10 }}>
<Text>{1000 + n}</Text>
</View>
))}
</View>
</ScrollView>
{_.times(200, n => (
<View key={n} style={{ marginRight: 10 }}>
<Text>{n}</Text>
</View>
))}
</View>
</ScrollView>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'stretch',
paddingVertical: 50,
},
});
另一方面,除了垂直滚动之外,相同的代码完全有效: https://snack.expo.io/@harrytravelchime/working-vertical-scroll
有没有办法使嵌套水平滚动起作用?
我想出的一个解决方案是 TouchableWithoutFeedback
跟踪用户在内部 ScrollView 中的任何触摸。一旦检测到触摸,它就会禁用外部 ScrollView 上的滚动,这会导致内部 ScrollView 接收事件。
以上代码的主要变化是:
- 添加状态
outerScrollViewScrollEnabled
- 当通过
TouchableWithoutFeedback
触摸内部 ScrollView 时,更改该状态 - 使外部 ScrollView 的
scrollEnabled
依赖于它
import React from "react";
import _ from "lodash";
import {
View,
ScrollView,
StyleSheet,
Text,
SafeAreaView,
TouchableWithoutFeedback
} from "react-native";
interface State {
outerScrollViewScrollEnabled: boolean;
}
export default class App extends React.PureComponent {
state = { outerScrollViewScrollEnabled: true };
handleInnerPressIn = () => this.setState({ outerScrollViewScrollEnabled: false });
handleInnerPressOut = () => this.setState({ outerScrollViewScrollEnabled: true });
render() {
const { outerScrollViewScrollEnabled } = this.state;
return (
<SafeAreaView style={styles.container}>
<ScrollView
style={{ height: "100%", width: "100%" }}
horizontal
scrollEnabled={outerScrollViewScrollEnabled}
>
<View style={{ flexDirection: "row" }}>
<ScrollView style={{ width: 200, height: "100%" }} horizontal>
<TouchableWithoutFeedback
onPressIn={this.handleInnerPressIn}
onPressOut={this.handleInnerPressOut}
>
<View style={{ flexDirection: "row" }}>
{_.times(200, n => (
<View key={1000 + n} style={{ marginRight: 10 }}>
<Text>{1000 + n}</Text>
</View>
))}
</View>
</TouchableWithoutFeedback>
</ScrollView>
{_.times(200, n => (
<View key={n} style={{ marginRight: 10 }}>
<Text>{n}</Text>
</View>
))}
</View>
</ScrollView>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
justifyContent: "center",
alignItems: "stretch",
paddingVertical: 50
}
});
如果您使用的是 react-native-gesture-handler,还有一种更简单的解决方案
import { ScrollView } from 'react-native'
import { ScrollView as GestureHandlerScrollView } from 'react-native-gesture-handler'
<ScrollView horizontal>
<GestureHandlerScrollView horizontal />
</ScrollVIew>
我从 react-native 那里得到了这个答案 github issue