web-dev-qa-db-fra.com

React Native: la définition de flex: 1 sur un ContentContainerStyle de ScrollView provoque un chevauchement de composants

Problème:

J'ai un ScrollView avec 2 sous-vues et je veux que le premier d'entre eux (appelons-le ViewA) ait {flex: 1} pour que l'autre (ViewB) reste au bas de l'écran - mais seulement si leur hauteur totale est plus petit que l'écran. Bien sûr que s’ils sont plus hauts que l’écran, je veux qu’il défile normalement.

Cas 1 (BON): ViewA avec un texte long, ViewB le fait défiler. https://rnplay.org/apps/slCivA

Cas 2 (BAD): ViewA avec un texte court, ViewB ne colle pas au bas. https://rnplay.org/apps/OmQakQ

Solution essayée:

Donc, je règle le style de ScrollView ET contentContainerStyle sur flex: 1. I Définissez également le style de ViewA sur flex: 1. Mais lorsque je le fais, la vue contentContainer de ScrollView est fixée à la hauteur de l'écran, donc impossible de faire défiler si nécessaire et pire encore - ViewB chevauche ViewA.

Cas 3 (BAD): ViewB colle au bas, mais le tout ne défile pas. https://rnplay.org/apps/wZgtWA

S'il s'agit d'un bogue - comment le résoudre/résoudre le problème? Si c'est le comportement attendu - comment puis-je obtenir ce que j'ai décrit?

Merci.

7
David Avikasis

Ok, donc je n'ai pas réussi à le faire fonctionner en le coiffant seul, mais voici comment je l'ai fait:

  1. Mesurer la hauteur du pied de page après son rendu (en utilisant onLayout et measure)
  2. sur le callback measure, j'ajoute la hauteur (si nécessaire) à une vue d'espacement entre ViewA et ViewB afin de placer ViewB sur le bas.
  3. Afin d'éviter d'afficher des "sauts" à l'utilisateur, je cache (avec l'opacité) ViewB jusqu'à ce que sa position soit fixée.

mon code CJSX (version simplifiée et simplifiée):

Dimensions = require('Dimensions')
windowSize = Dimensions.get('window')

MyClass = React.createClass
  mixins: [TimerMixin]

  render: ->
    <ScrollView style={styles.container} automaticallyAdjustContentInsets={false}>
      <View style={styles.mainContainer}>
        ... THIS IS VIEW A ...      
      </View>
      {
        if [email protected]
          <View>
            <ActivityIndicatorIOS/>
          </View>
      }
      <View style={[styles.spacer, {height: @state.spacerSize || 0}]}></View>
      <View onLayout={@measureFooterPosition} style={[styles.extras, {opacity: if @state.footerWasFixed then 1 else 0 }]} ref='extras'>
        ... THIS IS VIEW B ...       
      </View>
    </ScrollView>


  measureFooterPosition: ->
    @refs.extras.measure(@fixFooterPosition)

  fixFooterPosition: (ox, oy, width, height) ->
    footerPosition = Math.round(oy + height)
    diff = windowSize.height - footerPosition
    if diff > 0
      @setState(spacerSize: diff)
    if [email protected]
      @setTimeout (=>
        @setState(footerWasFixed: true)
      ), 30

styles = StyleSheet.create(
  container:
    backgroundColor: 'grey'
    flex: 1
  spacer:
    backgroundColor: 'white'
  mainContainer:
    flex: 1
    backgroundColor: 'white'
  extras:
    backgroundColor: 'white')

C'est un code très simplifié (mon point de vue a des exigences bien plus spécifiques que cela ..) mais j'espère que cela aidera n'importe qui.

5
David Avikasis

Essayez d'alimenter {flexGrow: 1} au contentContainerStyle prop à la place

35
Collin Tharp

Ok, j'ai fait un échantillon ici , et je pense avoir résolu le problème. La principale chose que j'ai faite a été de créer une vue de conteneur principale avec deux vues internes, puis de définir une flexion des vues internes à 80% et 20% (vous pouvez l'ajuster pour obtenir l'apparence souhaitée). 

https://rnplay.org/apps/O4UxFA

0
Nader Dabit