web-dev-qa-db-ja.com

React Native:ScrollView使用時の垂直方向のセンタリング

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の一番下までスクロールさせるにはどうすればよいですか?

44
Johnny Oshika

FlexではなくflexGrowでこの問題を解決しました

<ScrollView contentContainerStyle={{flexGrow: 1}}>

これにより、コンテンツコンテナが拡大してScrollViewがいっぱいになりますが、最大の高さは制限されないため、コンテンツがScrollViewの境界を拡張する場合でも正しくスクロールできます。

125
Jake Coxon

私のアプローチは次のとおりです。

flex : 1で外部コンテナを使用する場合、スクロールビューにはcontentContainerStyleではなくstyleを使用する{flexGrow : 1, justifyContent : 'center'}が必要です。

<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 : { }, })
39
Elden Skloss

編集:<ScrollView contentContainerStyle={{flexGrow: 1}}>を使用できるようになりました。

旧バージョンのReact flexGrowをサポートしないネイティブの場合、以下のソリューションを使用してください。


IOSとAndroidの両方でこれを確実に行う唯一の方法は、内部ビューのminHeightScrollViewのサイズに設定することです。 :

<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}
>
4
SteveMellross

新しいソリューションがあります(残念ながら、現時点ではiOSのみです)-Scrollviewで centerContent propを使用できます。

4
Radek Czemerys

なぜScrollView内の2番目のページだけをラップしないのですか?

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

最初の例を変更するだけで、それは魅力のように機能します:)

1
Michał Kisiel

ScrollView自体を垂直方向に中央に配置するには、次のような構造が必要です。

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

それ以外の場合、ScrollViewコンテンツ自体を中央に配置するには、次のものが必要です。

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