React Native:使用ScrollView时垂直居中


71

我正在使用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到了contentContainerStyle滚动型的。这样可以解决第1页的垂直居中问题,但是我不再能够一直向下滚动到第2页的底部。

https://rnplay.org/apps/LSgbog

如何解决此问题,以便在第1页上获得元素的垂直居中,但仍使ScrollView一直滚动到第2页的底部?


您是否能够找到解决方案?
Zach

1
@Zach不行,但我已经有一段时间没有对此进行研究了。这还是一个问题吗?
约翰尼·奥希卡

@JohnnyOshika您可以接受我的回答吗?它帮助了很多人
Jake Coxon '18

1
@JakeCoxon完成,谢谢!
约翰尼·奥什卡

Answers:


220

我用flexGrow而不是flex解决了这个问题

<ScrollView contentContainerStyle={{ flexGrow: 1, justifyContent: 'center' }}>

这使内容容器可以拉伸以填充ScrollView,但不限制最大高度,因此当内容扩展ScrollView的边界时,仍可以正确滚动


2
最后,您让我了解了flexGrow的用处
Younes Henni博士,

小小的解释使我很好理解。我被困了几个小时。
德拉利

2
实际上,仍然需要<ScrollView contentContainerStyle={{flexGrow: 1, justifyContent: 'center'}}>如下面的答案中所述。
彼得·贝拉

这将是最简单的使用方法:-<ScrollView contentContainerStyle = {{alignItems:'center'}}>
约翰

61

这是我的方法:

使用带有的外部容器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 vertical
      </View>
  </ScrollView>
</View> 

样式:

const styles = StyleSheet.create({scrollView : {
height : Dimensions.get('window').height, }, mainContainer : {
flex : 1 }, scrollViewContainer : { }, })


4

编辑:您现在可以使用<ScrollView contentContainerStyle={{flexGrow: 1}}>

对于不支持的旧版本的React Native,请flexGrow使用以下解决方案。


我发现可靠地对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}
>

3

为了使ScrollView自身垂直居中,则需要具有以下结构:

<View style={{flex: 1}}>
  <View>
   <ScrollView .../>
  </View>
</View>

否则,如果您想将ScrollView内容本身居中,则需要满足以下条件:

<ScrollView contentContainerStyle={{flexGrow : 1, justifyContent : 'center'}} ...>

1

为什么不只在ScrollView中包装第二页?

return (
    <ScrollView >
        <View style={styles.lipsum}>
            {this.renderButton()}
            <Text style={styles.lipsumText}>{lipsumText}</Text>
        </View>
    </ScrollView>
  );

只需修改您的第一个示例,它就像一个魅力:)


1
我想这是一个选择,它是一个很好的建议,但是在我的实际用例中,总是在顶部出现一个标题(带有徽标,标记行等),并且它也需要成为ScrollView的一部分。将ScrollView移到子视图意味着页眉不再滚动,否则我必须在所有子视图中重复该页眉。
约翰尼·奥希卡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.