flatlist - Cuadrícula ListView en React Native
scrollview react native (8)
Estoy creando una aplicación simple en React Native que obtiene listados de una fuente JSON remota y los muestra en la pantalla.
Hasta ahora, usando el excelente example aquí, he logrado que los resultados se muestren usando los componentes ListView en filas (es decir, 1 resultado por fila, ver captura de pantalla). Necesito que los resultados se muestren en una cuadrícula, es decir, de 3 a 6 elementos por fila, según el tamaño y la orientación de la pantalla.
¿Cuál es la mejor manera de obtener estos resultados en una cuadrícula? ¿Puedo usar ListView para esto, o es solo para resultados de uno por fila? He intentado jugar con estilos de flexbox pero, dado que React no parece aceptar los valores de% y ListView no acepta estilos, todavía no he tenido éxito.
Consulte el siguiente ejemplo utilizando el componente FlatList de React Native para admitir el desplazamiento infinito con un rendimiento excelente:
//Resize the grid
onLayout = (event) => {
const {width} = event.nativeEvent.layout;
const itemWidth = 150
const numColumns = Math.floor(width/itemWidth)
this.setState({ numColumns: numColumns })
}
render() {
return (
<Content
contentContainerStyle={{flex:1, alignItems: ''center''}}
onLayout={this.onLayout}>
<FlatList
data={this.state.products}
keyExtractor={(item, index) => index}
key={this.state.numColumns}
numColumns={this.state.numColumns}
renderItem={({item}) =>
<ListThumb //Custom component, it''s only an example.
navigation={navigation}
brand={item.brand}
price={item.price}
imageSource={item.image_link}/>
}
/>
</Content>
)
}
El ejemplo se ve así
Saludos cordiales, Nicholls
Estoy agregando esto como respuesta porque los comentarios de desbordamiento están ocultos bajo la respuesta de Colin Ramsay: a partir de React Native 0.28, también necesita
alignItems: ''flex-start'',
en el estilo de vista de lista o el flexWrap no funcionará.
Gracias a Kerumen en codedump.io por esto.
Entonces,
var styles = StyleSheet.create({
list: {
flexDirection: ''row'',
flexWrap: ''wrap'',
alignItems: ''flex-start'',
},
... con el resto como en la respuesta de Colin.
ListView ahora está en
deprecated
y debería usar
FlatList
en
FlatList
lugar.
FlatList tiene un accesorio llamado
numColumns
que es exactamente lo que queremos para crear una cuadrícula desplazable.
Por ejemplo:
const data = [
{id: ''a'', value: ''A''},
{id: ''b'', value: ''B''},
{id: ''c'', value: ''C''},
{id: ''d'', value: ''D''},
{id: ''e'', value: ''E''},
{id: ''f'', value: ''F''},
];
const numColumns = 3;
const size = Dimensions.get(''window'').width/numColumns;
const styles = StyleSheet.create({
itemContainer: {
width: size,
height: size,
},
item: {
flex: 1,
margin: 3,
backgroundColor: ''lightblue'',
}
});
function Grid(props) {
return (
<FlatList
data={data}
renderItem={({item}) => (
<View style={styles.itemContainer}>
<Text style={styles.item}>{item.value}</Text>
</View>
)}
keyExtractor={item => item.id}
numColumns={numColumns} />
);
}
Esta publicación de blog hace un buen trabajo explicando las nuevas características de FlatList.
Nota: Por alguna razón, debe usar
keyExtractor
en la FlatList en lugar del típico accesorio de
key
en cada elemento.
De lo contrario, recibirá una advertencia.
Código básico FlatList arroja Advertencia - React Native
Puede usar FlatList y establecer numColumns para obtener el resultado que es el mismo con la cuadrícula
Sigue la respuesta de Colin Ramsay. Y si desea la mitad del ancho de cada elemento, intente de esta manera.
...
import { Dimensions } from ''react-native'';
const { width, height } = Dimensions.get(''window'');
const gutter = 0; // You can add gutter if you want
...
const styles = StyleSheet.create({
item: {
width: (width - gutter * 3)/2,
marginBottom: gutter,
flexDirection: ''column'',
alignSelf: ''flex-start'',
backgroundColor: ''#ff0000'',
},
list: {
flexDirection: ''row'',
justifyContent: ''space-between'',
flexWrap: ''wrap'',
paddingHorizontal: gutter,
},
});
Tuve el mismo problema y escribí un componente que resuelve ese problema, puede encontrarlo aquí: https://github.com/pavlelekic/react-native-gridview
Además, otra cosa que hace este componente es asegurarse de que el ancho de los elementos sea un número entero, de modo que los bordes de los elementos no tengan suavizado, sean claros y nítidos.
use FlatList en lugar de Listview en react-native. Tiene más características de valor agregado y mejor rendimiento. FlatList
flexbox
utilizar una combinación de
flexbox
y saber que ListView envuelve ScrollView y, por lo tanto, adquiere sus propiedades.
Con eso en mente, puede usar el contenido
contentContainerStyle
de ScrollView para
contentContainerStyle
los elementos.
var TestCmp = React.createClass({
getInitialState: function() {
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
var data = Array.apply(null, {length: 20}).map(Number.call, Number);
return {
dataSource: ds.cloneWithRows(data),
};
},
render: function() {
return (
<ListView contentContainerStyle={styles.list}
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text style={styles.item}>{rowData}</Text>}
/>
);
}
});
Solo un ListView con algunos datos ficticios.
Tenga en cuenta el uso de
contentContainerStyle
.
Aquí está el objeto de estilo:
var styles = StyleSheet.create({
list: {
flexDirection: ''row'',
flexWrap: ''wrap''
},
item: {
backgroundColor: ''red'',
margin: 3,
width: 100
}
});
Le decimos al contenedor que queremos elementos en una fila de ajuste y establecemos el ancho de cada objeto secundario.