it-swarm.com.de

Reagieren Sie nativ: Das Festlegen von flex: 1 in einem ScrollView contentContainerStyle bewirkt, dass Komponenten überlappen

Problem:

Ich habe ein ScrollView mit 2 Unteransichten und ich möchte, dass die erste von ihnen (wie ViewA genannt) {flex: 1} hat, sodass die andere (ViewB) am unteren Rand des Bildschirms bleibt - aber nur, wenn ihre Gesamthöhe ist kleiner als der Bildschirm. Wenn sie höher als der Bildschirm sind, möchte ich natürlich, dass sie wie gewohnt scrollen.

Fall 1 (GUT): ViewA mit langem Text, ViewB scrollt mit. https://rnplay.org/apps/slCivA

Fall 2 (BAD): ViewA mit kurzem Text, ViewB bleibt nicht an der Unterseite. https://rnplay.org/apps/OmQakQ

Versuchte Lösung:

Also habe ich den Stil von ScrollView UND contentContainerStyle auf flex gesetzt: 1. I Setze auch den Style von ViewA auf flex: 1. Wenn ich dies jedoch mache, ist die contentContainer-Ansicht der ScrollView auf die Bildschirmhöhe festgelegt, sodass bei Bedarf kein Bildlauf möglich ist. Schlimmer noch - ViewB überlappt ViewA.

Fall 3 (BAD): ViewB bleibt unten, aber das Ganze rollt nicht. https://rnplay.org/apps/wZgtWA

Wenn es sich um einen Fehler handelt - wie kann er behoben werden? Wenn es sich um das erwartete Verhalten handelt - wie kann ich das erreichen, was ich beschrieben habe?

Vielen Dank.

7
David Avikasis

Ok, also konnte ich es nicht alleine durch das Styling schaffen, aber so habe ich es gemacht:

  1. Messen Sie die Höhe der Fußzeile nach dem Rendern (mithilfe von onLayout und measure)
  2. beim measure-Callback füge ich die Höhe (falls erforderlich) zu einer Abstandsansicht zwischen ViewA und ViewB hinzu, um ViewB unten zu platzieren.
  3. Um zu vermeiden, dass dem Benutzer "Sprünge" angezeigt werden, blende ich ViewB (mit Deckkraft) aus, bis seine Position festgelegt ist.

mein CJSX-Code (abgespeckte und vereinfachte Version):

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')

Es ist sehr vereinfachter Code (aus meiner Sicht sind die Anforderungen viel spezifischer als dieser ..), aber ich hoffe, es hilft jedem.

5
David Avikasis

Versuchen Sie stattdessen, {flexGrow: 1} an die contentContainerStyle prop zu übergeben

35
Collin Tharp

Ok, ich habe eine Probe hier gemacht, und ich denke, ich habe das Problem gelöst. Ich habe vor allem eine Hauptcontaineransicht mit zwei Innenansichten erstellt und dann die Innenansichten auf 80% und 20% eingestellt (Sie können anpassen, damit sie so aussehen, wie Sie möchten). 

https://rnplay.org/apps/O4UxFA

0
Nader Dabit