2016-01-22 9 views
7

Nachdem ich in den letzten Wochen mit dem nativen iOS-System gearbeitet habe, bin ich auf einige Mängel des Flex-Stylings gestoßen ... Vor allem, wenn es um "reaktionsschnelles" Verhalten geht.Reagieren native Flexbox - wie prozentuale Werte || Spalten || reagierend || Grid usw.

Nehmen wir beispielsweise an, Sie möchten eine Ansicht erstellen, die Karten enthält (die Metadaten für diese Karten stammen von einer API). Sie wollen die Karten 50% der Ansicht Breite minus den Rand & Polsterung und zu wickeln nach jedem 2.

enter image description here

Die aktuelle Implementierung ich für diese Ansicht haben die zurückgegebene Array in Zeilen teilt mit 2 Artikel. Der Listencontainer hat flex: 1, flexDirection: 'column, die Zeilen haben flex: 1 und dann hat jede Karte flex: 1. Das Endergebnis ist, dass jede Zeile 2 Spalten hat, die gleichmäßig die Hälfte der Ansichtsbreite einnehmen.

Es scheint, als gäbe es keine triviale Möglichkeit, dies in nativen React-Stilen zu tun, ohne JavaScript zu verwenden, um eine Art Vorverarbeitung der Daten durchzuführen, so dass es korrekt formatiert wird. Hat jemand irgendwelche Vorschläge?

+0

Haben Sie "flexWrap" versuchen? –

+0

Ja, aber flexWrap funktioniert nur, wenn es einen Überlauf von untergeordneten Elementen gibt, der nur ausgelöst werden kann, wenn eine width-Eigenschaft für die untergeordneten Elemente angegeben ist. @ niceass –

+0

Und was ist falsch mit der Angabe einer 50% Breite? Willst du das überhaupt nicht? –

Antwort

1

Reagieren india bereits has percentage support:

<View style={[style.parent]}> 
    <View style={[style.child, {backgroundColor: '#996666'} ]} /> 
    <View style={[style.child, {backgroundColor: '#339966'} ]} /> 
    <View style={[style.child, {backgroundColor: '#996633'} ]} /> 
    <View style={[style.child, {backgroundColor: '#669933'} ]} /> 
</View> 

var style = StyleSheet.create({ 
    parent: { 
     width: '100%', 
     flexDirection: 'row', 
     flexWrap: 'wrap' 
    }, 
    child: { 
     width: '48%', 
     margin: '1%', 
     aspectRatio: 1, 
    } 
}) 

enter image description here

17

Es kann eine bessere Möglichkeit, dies mit Flexbox zu erreichen, aber ich definieren in der Regel „Prozentsatz“ Helfer vw und vh für Darstellungsbreite und Darstellungshöhe, nachdem die CSS Darstellungsgröße Maßeinheiten genannt:

import {Dimensions} from 'react-native'; 

function vw(percentageWidth) { 
    return Dimensions.get('window').width * (percentageWidth/100); 
} 

function vh(percentageHeight) { 
    return Dimensions.get('window').height * (percentageHeight/100); 
} 

Um Elemente in einem Raster zu fließen, können Sie dann eine geeignete Größe für die Einzelteile, auf die Margen und die Anzeigengröße berechnen:

const COLUMNS = 3; 
const MARGIN = vw(1); 
const SPACING = (COLUMNS + 1)/COLUMNS * MARGIN; 

const grid = { 
    flex: 1, 
    flexWrap: 'wrap', 
    flexDirection: 'row', 
    justifyContent: 'flex-start' 
}; 

const cell = { 
    marginLeft: MARGIN, 
    marginTop: MARGIN, 
    width: vw(100)/COLUMNS - SPACING 
} 

return (
    <View style={grid}> 
    {this.props.things.map(thing => <View style={cell} />)} 
    </View> 
) 

Sie sollten nur diese Technik verwenden, wenn Sie einen bekannten und limite haben d Anzahl der Elemente - Für eine beliebige Anzahl von Karten sollten Sie aus Leistungsgründen ListView verwenden und Ihren Datensatz manuell in Zeilen aufteilen.

+0

Dies scheint die beste Lösung bisher zu sein. Danke für das Teilen von @jevakallio. –

+1

Problem mit diesem Ansatz ist, dass es nicht funktioniert, wenn Sie zulassen, dass die Ausrichtung geändert wird. – Joon

+0

@Joon korrekt - Ich habe gerade eine Bibliothek veröffentlicht, die es einfacher macht, native Komponenten sowohl im Hoch- als auch im Querformat zu formatieren: https://github.com/FormidableLabs/react-native-responsive-styles – jevakallio

0

Sie justifyContent verwenden können: 'raum zwischen'

<View style={styles.feed}> 
    <View style={styles.card} /> 
    <View style={styles.card} /> 
    <View style={styles.card} /> 
    <View style={styles.card} /> 
</View> 

feed: { 
flex: 1, 
flexDirection: 'row', 
flexWrap: 'wrap', 
padding: 16, 
justifyContent: 'space-between' } 


card: { 
backgroundColor: 'white', 
width: '48%', 
aspectRatio: 1, 
marginBottom: 16 } 

screenshot