Native reagieren: Vertikale Zentrierung bei Verwendung von ScrollView

71

Ich verwende React Native und habe Probleme, die vertikale Zentrierung von Elementen beizubehalten, sobald ich eine ScrollView einführe. Zur Demonstration habe ich 3 Apps mit React Native Playground erstellt. Alle Beispiele haben 2 Seiten und können durch Tippen auf die blaue Schaltfläche umgeschaltet werden.

Beispiel 1:

Dieses erste Beispiel zeigt Blöcke, die vertikal auf Seite 2 zentriert sind. Dies geschieht, weil auf den Container die folgenden Stile angewendet werden:

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

https://rnplay.org/apps/lb5wSQ

Sobald Sie jedoch zu Seite 2 wechseln, tritt ein Problem auf, da der gesamte Inhalt der Seite nicht passt. Wir benötigen daher ein ScrollView.

Beispiel 2

In diesem Beispiel verpacke ich alles in eine ScrollView. Dadurch kann Seite 2 scrollen, aber jetzt habe ich die vertikale Zentrierung von Seite 1 verloren.

https://rnplay.org/apps/DCgOgA

Beispiel 3

Um zu versuchen, die vertikale Zentrierung von Seite 1 wiederherzustellen, wende ich mich flex: 1an contentContainerStyleScrollView an. Dadurch wird die vertikale Zentrierung auf Seite 1 behoben, aber ich kann auf Seite 2 nicht mehr ganz nach unten scrollen.

https://rnplay.org/apps/LSgbog

Wie kann ich das beheben, damit die Elemente auf Seite 1 vertikal zentriert werden und ScrollView dennoch auf Seite 2 ganz nach unten scrollen kann?

Johnny Oshika
quelle
Konnten Sie eine Lösung dafür finden?
Zach
1
@ Zach Nein, aber ich habe mir das schon eine ganze Weile nicht mehr angesehen. Ist das noch ein Problem?
Johnny Oshika
@ JohnnyOshika könntest du meine Antwort akzeptieren? Es hat vielen Menschen geholfen
Jake Coxon
1
@ JakeCoxon Fertig, danke!
Johnny Oshika

Antworten:

219

Ich habe dieses Problem mit flexGrow anstelle von flex gelöst

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

Dadurch wird der Inhaltscontainer gedehnt, um die ScrollView zu füllen, ohne die maximale Höhe einzuschränken. Sie können also weiterhin korrekt scrollen, wenn der Inhalt die Grenzen der ScrollView erweitert

Jake Coxon
quelle
2
Endlich haben Sie mir die Nützlichkeit von flexGrow verständlich gemacht
Dr. Younes Henni
Die kleine Erklärung lässt mich sehr gut verstehen. Ich war stundenlang damit beschäftigt.
Delali
2
Es muss tatsächlich noch <ScrollView contentContainerStyle={{flexGrow: 1, justifyContent: 'center'}}>wie in den Antworten unten erwähnt.
Petr Bela
Dies ist am einfachsten zu verwenden: - <ScrollView contentContainerStyle = {{alignItems: 'center'}}>
John
61

Hier ist mein Ansatz:

Verwenden Sie einen äußeren Container mit flex : 1, dann muss die Bildlaufansicht {flexGrow : 1, justifyContent : 'center'}verwendet werden contentContainerStyle, nicht 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> 

Stile:

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

Es gibt eine neue Lösung (leider nur iOS im Moment) - wir können centerContentprop auf Scrollview verwenden.

Radek Czemerys
quelle
2
Dies ist nur für iOS verfügbar, eine Option für Android?
Devansh Sadhotra
4

EDIT: Sie können jetzt verwenden <ScrollView contentContainerStyle={{flexGrow: 1}}>.

flexGrowVerwenden Sie für ältere Versionen von React Native, die nicht unterstützt werden , die folgende Lösung.


Die einzige Möglichkeit, dies sowohl für iOS als auch für Android zuverlässig zu tun, besteht darin, minHeightdie innere Ansicht auf die Größe des zu setzen ScrollView. Z.B:

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

Hinweis: Der Einfachheit halber habe ich die oben genannten Stile und Funktionen integriert, aber Sie möchten wahrscheinlich konstante Referenzen für die unveränderlichen Werte verwenden und den sich ändernden Stil auswendig lernen, um unnötige erneute Darstellungen zu vermeiden.

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}
>
SteveMellross
quelle
3

Um ScrollView selbst vertikal zu zentrieren, benötigen Sie eine solche Struktur:

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

Andernfalls benötigen Sie Folgendes, wenn Sie ScrollView-Inhalte selbst zentrieren möchten:

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

Warum verpacken Sie nicht nur die zweite Seite in eine ScrollView?

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

Ändern Sie einfach Ihr erstes Beispiel, es funktioniert wie ein Zauber :)

Michał Kisiel
quelle
1
Ich nehme an, das ist eine Option und ein großartiger Vorschlag, aber in meinem realen Anwendungsfall wird oben immer eine Kopfzeile angezeigt (mit Logo, Tag-Zeile usw.), die auch Teil der ScrollView sein muss. Wenn Sie die ScrollView in eine untergeordnete Ansicht verschieben, wird der Header nicht mehr gescrollt, oder ich muss den Header in allen untergeordneten Ansichten duplizieren.
Johnny Oshika