Сетка ListView в React Native
Я создаю простое приложение в React Native, которое извлекает списки из удаленного источника JSON и отображает их на экране.
До сих пор, используя отличный пример, мне удалось отобразить результаты, используя компоненты ListView в строках (т.е. 1 результат на строку, см. Скриншот). Мне нужно, чтобы результаты отображались в сетке, то есть от 3 до 6 элементов в строке, в зависимости от размера экрана и ориентации.
Каков наилучший способ получить эти результаты в сетке? Могу ли я использовать ListView для этого, или это только для результатов по одному на строку? Я попытался поиграть со стилями flexbox, но, поскольку кажется, что React не принимает значения%, а ListView не принимает стили, я пока не добился успеха.
8 ответов
Вам нужно использовать комбинацию flexbox и знание того, что ListView оборачивает ScrollView и таким образом принимает его свойства. Имея это в виду, вы можете использовать ScrollView contentContainerStyle
опора для стиля предметов.
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>}
/>
);
}
});
Просто ListView с некоторыми фиктивными данными. Обратите внимание на использование contentContainerStyle
, Вот объект стиля:
var styles = StyleSheet.create({
list: {
flexDirection: 'row',
flexWrap: 'wrap'
},
item: {
backgroundColor: 'red',
margin: 3,
width: 100
}
});
Мы сообщаем контейнеру, что нам нужны элементы в строке переноса, и устанавливаем ширину каждого дочернего объекта.
ListView устарел, и вы должны использовать FlatList. FlatList имеет реквизит numColumns
это именно то, что мы хотим создать прокручиваемую сетку.
Например:
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} />
);
}
Этот пост в блоге хорошо объясняет новые функции FlatList.
Примечание: по какой-то причине вы должны использовать keyExtractor
на FlatList вместо типичного key
опора на каждый предмет. В противном случае вы получите предупреждение. Основной код FlatList выдает предупреждение - React Native
Я добавляю это как ответ, потому что комментарии переполнения скрыты под ответом Колина Рэмси: начиная с React Native 0.28, вам также нужно alignItems: 'flex-start',
в стиле списка или FlexWrap не будет работать. Спасибо Керумену на codedump.io за это. Так,
var styles = StyleSheet.create({
list: {
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'flex-start',
},
... с остальным, как в ответе Колина.
У меня была такая же проблема, и я написал компонент, который решает эту проблему, вы можете найти его здесь: https://github.com/pavlelekic/react-native-gridview
Кроме того, еще одна вещь, которую делает этот компонент, - он гарантирует, что ширина элементов - это целое число, чтобы границы элементов не имели сглаживания, они были четкими и четкими.
Следуйте ответу Колина Рамсея. И если вы хотите половину ширины для каждого элемента, попробуйте этот путь.
...
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,
},
});
Используйте FlatList вместо Listview в реагировать на родной. у него больше добавленной стоимости и лучшая производительность. проверить пример здесь
Вы можете использовать FlatList и установить numColumns для получения результата, который совпадает с сеткой
Проверьте следующий пример, используя компонент FlatList React Native для поддержки бесконечной прокрутки с превосходной производительностью:
//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>
)
}
Пример выглядит так
С наилучшими пожеланиями, Николс
ScrollView с опорой contentContainerStyle работал у меня
<ScrollView contentContainerStyle={{ flexDirection: "row", flexWrap: "wrap", alignContent: "center",}}>
{user.posts.map((post, index) => (
<Image
source={require(post.uri)}
key={index}
style={{ width: 100, height: 100 }}
/>
))}
</ScrollView>