Solución:
Una buena forma en que hemos hecho esto en producción en el pasado, y ha funcionado bien, es obtener el ancho del contenedor y establecer el ancho de las tarjetas al 50% del ancho, luego puede presionar todo el elementos individuales en la vista de lista. Además, asegúrese de configurar un flexWrap
de wrap
.
Esto funcionará en todos los tamaños de dispositivos y no requiere módulos ni bibliotecas adicionales.
Consulte el código de muestra a continuación y el ejemplo aquí:
https://rnplay.org/apps/t_6-Ag
/* Get width of window */
const width = Dimensions.get('window').width
/* ListView */
<ListView
contentContainerStyle={styles.listView}
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
/>
/* Row */
renderRow () {
return <View style={styles.card}>
<Text>{rowData.name} {rowData.price}</Text>
</View>
/* Styles */
listView: {
flexDirection: 'row',
flexWrap: 'wrap'
},
card: {
backgroundColor: 'red',
width: (width / 2) - 15,
height: 300,
marginLeft: 10,
marginTop: 10
}
React Native tiene un buen ejemplo de esto en su CameraRollView.js
ejemplo. Usan una biblioteca llamada groupByEveryN
para permitirle establecer cuántos elementos se renderizarán por fila.
Observe el cambio en la forma en que inicia la ListView.DataSource
…
var ds = new ListView.DataSource({rowHasChanged: this._rowHasChanged});
this.state.dataSource = ds.cloneWithRows(
groupByEveryN(this.state.assets, this.props.imagesPerRow)
);
Tu renderRow
la función solo necesita esperar una variedad de elementos …
// rowData is an array of images
_renderRow: function(rowData: Array<Image>, sectionID: string, rowID: string) {
var images = rowData.map((image) => {
if (image === null) {
return null;
}
return this.props.renderImage(image);
});
return (
<View style={styles.row}>
{images}
</View>
);
}
Archivo de ejemplo completo aquí: https://github.com/facebook/react-native/blob/a564af853f108e071e941ac08be4cde864f5bfae/Examples/UIExplorer/js/CameraRollView.js.