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 à la page 2. Cela se produit parce que ces styles sont appliqués au conteneur il:

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'enroule tout à l'intérieur D'un ScrollView. Cela permet à la page 2 de faire défiler, mais maintenant j'ai perdu le centrage vertical de la Page 1.

Https://rnplay.org/apps/DCgOgA

Exemple 3

Afin de essayez de récupérer le centrage vertical de la Page 1, j'applique flex: 1 au contentContainerStyle de ScrollView. Cela corrige le centrage vertical sur la page 1, mais je ne suis plus en mesure de faire défiler tout le chemin vers le bas sur la page 2.

Https://rnplay.org/apps/LSgbog

Comment puis-je résoudre ce problème pour obtenir le centrage vertical des éléments sur la page 1 tout en obtenant ScrollView pour faire défiler tout le chemin vers le bas sur la page 2?

29
demandé sur Johnny Oshika 2015-09-19 07:58:31

5 réponses

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

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

Cela permet au conteneur de contenu de s'étirer pour remplir le ScrollView mais ne limite pas la hauteur maximale, de sorte que vous pouvez toujours faire défiler correctement lorsque le contenu étend les limites du ScrollView

64
répondu Jake Coxon 2017-04-05 09:53:01

Voici mon approche:

Utilisez un conteneur externe avec flex : 1, alors 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> 

Styles:

const styles = StyleSheet.create({scrollView : {
height : Dimensions.get('window').height, }, mainContainer : {
flex : 1 }, scrollViewContainer : { }, })
18
répondu Elden Skloss 2018-04-05 08:58:41

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

4
répondu Radek Czemerys 2017-03-29 13:04:01

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

Pour les anciennes versions de React Native qui ne prennent pas en charge flexGrow, Utilisez la solution ci-dessous.


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

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

Note: j'ai intégré les styles et les fonctions ci-dessus pour plus de simplicité, mais vous voudrez probablement utiliser des références constantes pour les valeurs immuables et mémoriser le style changeant pour éviter les redirections 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
répondu SteveMellross 2017-08-26 06:47:54

Pourquoi ne pas envelopper seulement 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
répondu Michał Kisiel 2018-04-05 08:55:50