我正在使用 React Native,一旦引入 ScrollView,我就很难保持元素的垂直居中。为了进行演示,我使用 React Native Playground 创建了 3 个应用程序。所有示例都有 2 页,可以通过点击蓝色按钮进行切换。
示例1:
第一个示例显示第 2 页上垂直居中的块。发生这种情况是因为容器应用了以下样式:
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
https://rnplay.org/apps/lb5wSQ
但是,一切换到第2页就有问题了,因为页面的全部内容放不下,所以我们需要一个
ScrollView
。
示例2
在此示例中,我将所有内容包装在 ScrollView 中。这允许第 2 页滚动,但现在我失去了第 1 页的垂直居中。
https://rnplay.org/apps/DCgOgA
示例3
为了尝试恢复第 1 页的垂直居中,我将
flex: 1
应用于 ScrollView 的 contentContainerStyle
。这修复了第 1 页的垂直居中,但我无法再一直向下滚动到第 2 页的底部。
https://rnplay.org/apps/LSgbog
如何解决此问题,以便使第 1 页上的元素垂直居中,同时仍让 ScrollView 一直滚动到第 2 页的底部?
我用 flexGrow 而不是 flex 解决了这个问题
<ScrollView contentContainerStyle={{ flexGrow: 1, justifyContent: 'center' }}>
这使得内容容器拉伸以填充 ScrollView,但不限制最大高度,因此当内容扩展 ScrollView 的边界时,您仍然可以正确滚动
这是我的方法。
使用带有
flex : 1
的外容器,那么滚动视图需要使用 {flexGrow : 1, justifyContent : 'center'}
来具有 contentContainerStyle
,而不是 style
。
<View style={styles.mainContainer}>
<ScrollView
contentContainerStyle={{ flexGrow: 1, justifyContent: 'center' }}>
<View style={styles.scrollViewContainer}>
{/* Put your stuff here, and it will be centered vertically. */}
</View>
</ScrollView>
</View>
款式:
const styles = StyleSheet.create({
mainContainer: { flex: 1 },
scrollView: { height: Dimensions.get('window').height },
scrollViewContainer: {},
});
有一个新的解决方案(不幸的是目前仅适用于 iOS) - 我们可以在 Scrollview 上使用
centerContent
属性。
为了使 ScrollView 本身垂直居中,那么你需要有这样的结构:
<View style={{flex: 1}}>
<View>
<ScrollView .../>
</View>
</View>
否则,如果您想让 ScrollView 内容本身居中,那么您需要以下内容:
<ScrollView contentContainerStyle={{flexGrow : 1, justifyContent : 'center'}} ...>
编辑:您现在可以使用
<ScrollView contentContainerStyle={{flexGrow: 1}}>
。
对于不支持
flexGrow
的旧版本React Native,请使用以下解决方案。
我发现在 iOS 和 Android 上可靠地执行此操作的唯一方法是将内部视图的
minHeight
设置为 ScrollView
的大小。例如:
<ScrollView
style={{flex: 1}}
contentContainerStyle={{minHeight: this.state.minHeight}}
onLayout={event => this.setState({minHeight: event.nativeEvent.layout.height})}
>
注意:为了简单起见,我已经内联了上面的样式和函数,但您可能希望对不变的值使用常量引用并记住更改的样式以防止不必要的重新渲染。
const {minHeight} = this.state;
// Manually memorise changing style or use something like reselect...
if (this.lastMinHeight != minHeight) {
this.lastMinHeight = minHeight;
this.contentContainerStyle = {minHeight: minHeight}
}
<ScrollView
style={styles.scrollViewStyle}
contentContainerStyle={this.contentContainerStyle}
onLayout={this.onScrollViewLayout}
>
为什么不在 ScrollView 中只包装第二页?
return (
<ScrollView >
<View style={styles.lipsum}>
{this.renderButton()}
<Text style={styles.lipsumText}>{lipsumText}</Text>
</View>
</ScrollView>
);
只需修改您的第一个示例,它就像一个魅力:)