Grille de ListView en natif de React
je suis en train de construire une application simple dans React Native qui récupère les annonces d'une source distante JSON et les affiche à l'écran.
jusqu'à présent, en utilisant l'excellent exemple ici, j'ai réussi à obtenir les résultats à afficher en utilisant les composants ListView dans les lignes (i.e. 1 Résultat par ligne, voir screenshot). J'ai besoin que les résultats s'affichent dans une grille, c'est-à-dire de 3 à 6 éléments par rangée, selon la taille et l'orientation de l'écran.
quoi est la meilleure façon d'obtenir ces résultats dans une grille? Puis-je utiliser ListView pour cela, ou est-ce seulement pour un résultat par ligne? J'ai essayé de jouer avec les styles de flexbox, mais puisque React ne semble pas accepter % values et ListView n'accepte pas les styles, Je n'ai pas encore eu de succès.
8 réponses
vous devez utiliser une combinaison de flexbox , et la connaissance que ListView enveloppe ScrollView et prend ainsi sur ses propriétés. Avec cela à l'esprit, vous pouvez utiliser l'hélice contentContainerStyle
de ScrollView pour le style des articles.
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>}
/>
);
}
});
juste un ListView avec des données fictives. Notez l'utilisation de contentContainerStyle
. Voici l'objet style:
var styles = StyleSheet.create({
list: {
flexDirection: 'row',
flexWrap: 'wrap'
},
item: {
backgroundColor: 'red',
margin: 3,
width: 100
}
});
nous disons au conteneur que nous voulons des articles dans une rangée d'emballage, et le la largeur de chaque objet enfant.
j'ajoute ceci comme réponse parce que les commentaires de débordement sont cachés sous la réponse de Colin Ramsay: à partir de React Native 0.28, vous avez aussi besoin de alignItems: 'flex-start',
dans le style listview ou le flexWrap ne fonctionnera pas. Merci à Kerumen sur codedump.io pour ça. So,
var styles = StyleSheet.create({
list: {
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'flex-start',
},
...avec le reste comme dans la réponse de Colin.
ListView est maintenant déprécié et vous devez utiliser FlatList à la place. FlatList a un prop appelé numColumns
qui est exactement ce que nous voulons créer une grille scrollable.
par exemple:
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} />
);
}
Ce blog post fait un bon travail en expliquant les nouvelles fonctionnalités de FlatList.
Note: pour une raison quelconque, vous devez utiliser keyExtractor
sur la FlatList au lieu de l'hélice typique key
sur chaque élément. Sinon, vous recevrez un avertissement. Basic FlatList code says Warning-React Native
j'ai eu le même problème et j'ai écrit un composant qui résout ce problème, vous pouvez le trouver ici: https://github.com/pavlelekic/react-native-gridview
en outre, une autre chose que ce composant fait est qu'il s'assure que la largeur des articles est un nombre entier, de sorte que les bordures des articles n'ont pas antialiasing, ils sont clairs et croquants.
suivez la réponse de Colin Ramsay. Et si vous voulez la moitié de la largeur pour chaque élément, essayez de cette façon.
...
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,
},
});
utilisez FlatList au lieu de Listview dans react-native. il offre plus de fonctions à valeur ajoutée et de meilleures performances. vérifier l'exemple ici
vous pouvez utiliser FlatList et set numColumns pour obtenir le résultat qui est le même avec grid
cochez l'exemple suivant en utilisant FlatList composante de React Native pour supporter le défilement infini avec une excellente performance:
//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>
)
}
l'exemple ressemble à
meilleures salutations, Nicholls