web-dev-qa-db-fra.com

React Native: centrage vertical lors de l'utilisation de ScrollView

J'utilise React Native et j'ai du mal à conserver le centrage vertical des éléments dès que j'introduis un ScrollView. Pour démontrer, j'ai créé 3 applications avec React Native Playground. Tous les exemples ont 2 pages, et ils peuvent être basculés en appuyant sur le bouton bleu.

Exemple 1:

Ce premier exemple montre les blocs centrés verticalement sur la page 2. Cela se produit car les styles suivants sont appliqués au conteneur:

flex: 1,
flexDirection: 'column',
justifyContent: 'center',

https://rnplay.org/apps/lb5wSQ

Cependant, il y a un problème dès que vous passez à la page 2, car tout le contenu de la page ne correspond pas, nous avons donc besoin d'un ScrollView.

Exemple 2

Dans cet exemple, j'encapsule tout à l'intérieur d'un ScrollView. Cela permet à la page 2 de défiler, mais maintenant j'ai perdu le centrage vertical de la page 1.

https://rnplay.org/apps/DCgOgA

Exemple 3

Afin d'essayer de récupérer le centrage vertical de la page 1, j'applique flex: 1 Au contentContainerStyle de ScrollView. Cela corrige le centrage vertical à la page 1, mais je ne peux plus faire défiler jusqu'en bas de la page 2.

https://rnplay.org/apps/LSgbog

Comment puis-je résoudre ce problème afin d'obtenir un centrage vertical des éléments à la page 1 tout en continuant à faire défiler ScrollView jusqu'en bas de la page 2?

44
Johnny Oshika

J'ai résolu ce problème avec flexGrow au lieu de flex

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

Cela rend le conteneur de contenu étiré pour remplir le ScrollView mais ne limite pas la hauteur maximale, vous pouvez donc toujours faire défiler correctement lorsque le contenu étend les limites du ScrollView

125
Jake Coxon

Voici mon approche:

Utilisez un récipient extérieur avec flex : 1, la vue de défilement doit avoir {flexGrow : 1, justifyContent : 'center'} en utilisant contentContainerStyle, pas 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> 

Modes:

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

EDIT: Vous pouvez maintenant utiliser <ScrollView contentContainerStyle={{flexGrow: 1}}>.

Pour une ancienne version de React Native qui ne prend pas en charge flexGrow, utilisez la solution ci-dessous.


La seule façon que j'ai trouvée de le faire de manière fiable pour iOS et Android est de définir minHeight de la vue intérieure à la taille de ScrollView. Par exemple :

<ScrollView
    style={{flex: 1}}
    contentContainerStyle={{minHeight: this.state.minHeight}}
    onLayout={event => this.setState({minHeight: event.nativeEvent.layout.height})}
>

Remarque: J'ai intégré les styles et les fonctions ci-dessus pour plus de simplicité, mais vous souhaiterez probablement utiliser des références constantes pour les valeurs immuables et mémoriser le style changeant pour éviter les redondances inutiles.

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

Il y a une nouvelle solution (malheureusement iOS uniquement pour le moment) - nous pouvons utiliser centerContent prop sur Scrollview.

4
Radek Czemerys

Pourquoi ne pas envelopper uniquement la deuxième page dans un ScrollView?

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

Modifiez simplement votre premier exemple, cela fonctionne comme un charme :)

1
Michał Kisiel

Afin de centrer ScrollView lui-même verticalement, vous devez avoir ce type de structure:

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

Sinon, si vous souhaitez centrer le contenu ScrollView lui-même, vous avez besoin des éléments suivants:

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