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の一番下までスクロールさせるにはどうすればよいですか?
FlexではなくflexGrowでこの問題を解決しました
<ScrollView contentContainerStyle={{flexGrow: 1}}>
これにより、コンテンツコンテナが拡大してScrollViewがいっぱいになりますが、最大の高さは制限されないため、コンテンツがScrollViewの境界を拡張する場合でも正しくスクロールできます。
私のアプローチは次のとおりです。
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 : { }, })
編集:<ScrollView contentContainerStyle={{flexGrow: 1}}>
を使用できるようになりました。
旧バージョンのReact 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}
>
新しいソリューションがあります(残念ながら、現時点ではiOSのみです)-Scrollviewで centerContent
propを使用できます。
なぜScrollView内の2番目のページだけをラップしないのですか?
return (
<ScrollView >
<View style={styles.lipsum}>
{this.renderButton()}
<Text style={styles.lipsumText}>{lipsumText}</Text>
</View>
</ScrollView>
);
最初の例を変更するだけで、それは魅力のように機能します:)
ScrollView自体を垂直方向に中央に配置するには、次のような構造が必要です。
<View style={{flex: 1}}>
<View>
<ScrollView .../>
</View>
</View>
それ以外の場合、ScrollViewコンテンツ自体を中央に配置するには、次のものが必要です。
<ScrollView contentContainerStyle={{flexGrow : 1, justifyContent : 'center'}} ...>