2016-01-22 12 views
7

Dopo aver lavorato con nativo iOS su iOS per le ultime due settimane, mi sembra di aver riscontrato alcune carenze nello stile flessibile ... In particolare quando si tratta di comportamenti "reattivi".React flexbox nativo: come fare le percentuali || colonne || reattivo || griglia, ecc.

Ad esempio, diciamo che si desidera creare una vista che contenga le carte (i metadati di queste schede provengono da un'API). Si desidera le carte per essere il 50% della larghezza vista meno il padding margine di &, e per avvolgere dopo ogni 2.

enter image description here

L'implementazione corrente che ho per questo punto di vista divide la matrice restituita in righe con 2 elementi. Il contenitore dell'elenco ha flex: 1, flexDirection: 'column, le righe hanno lo flex: 1 e ogni scheda ha flex: 1. Il risultato finale è che ogni riga ha 2 colonne che occupano in modo uniforme metà della larghezza della vista.

Sembra che non ci sia un modo banale per farlo negli stili React Native, senza utilizzare javascript per eseguire una sorta di pre-elaborazione sui dati in modo che risulti correttamente. Qualcuno ha qualche suggerimento?

+0

Hai provato "flexWrap"? –

+0

Sì, ma flexWrap funziona solo in caso di overflow di bambini, che può essere attivato solo se è stata specificata una proprietà width sui figli. @niceass –

+0

E cosa c'è di sbagliato nel specificare una larghezza del 50%? Non è quello che vuoi comunque? –

risposta

1

Reagire Native già 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

Ci può essere un modo migliore per raggiungere questo obiettivo con FlexBox, ma io di solito definire aiutanti "percentuali" vw e vh per la larghezza viewport e l'altezza della vista, che prendono il nome le unità di dimensione CSS finestra di misura:

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); 
} 

per scorrere gli elementi in una griglia, è possibile quindi calcolare una dimensione appropriata per gli elementi, che rappresentano i margini e le dimensioni del riquadro:

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

si dovrebbe usare questa tecnica solo se si dispone di una nota e limite d numero di elementi - per quantità arbitrarie di carte, è necessario utilizzare ListView per motivi di prestazioni e dividere il set di dati in righe manualmente.

+0

Questa sembra la soluzione migliore finora. Grazie per aver condiviso @jevakallio. –

+1

Il problema con questo approccio è che non funzionerà se si consente di modificare l'orientamento. – Joon

+0

@Joon correct - Ho appena pubblicato una libreria che semplifica lo stile di reazione dei componenti nativi sia in orizzontale che in verticale: https://github.com/FormidableLabs/react-native-responsive-styles – jevakallio

0

È possibile utilizzare justifyContent: 'spazio-tra'

<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

Problemi correlati