反应本机中的 ListView 网格

我正在反应本机中构建一个简单的应用程序,它从远程 JSON 源获取列表并在屏幕上显示它们。

到目前为止,在这里使用优秀的 例子,我已经设法使用 ListView 组件在行中显示结果(即每行1个结果,见屏幕快照)。我需要的结果显示在一个网格,即每行3至6项,取决于屏幕大小和方向。

将这些结果放入网格的最佳方法是什么?我可以使用 ListView 进行此操作吗? 还是仅对每行一个结果使用 ListView?我曾经尝试过使用 Flexbox 样式,但是由于 React 似乎不接受% 值,ListView 也不接受样式,所以我还没有取得任何成功。

This is how my listings are displaying at the moment - one per row.

73923 次浏览

您需要结合使用 弹簧箱和 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
}
});

我们告诉容器我们想要一个包装行中的项目,并且我们设置每个子对象的宽度。

Screenshot

我添加这个作为一个答案,因为溢出注释是隐藏在 Colin Ramsay 的回应: 作为反应本机0.28,您还需要在列表视图样式的 alignItems: 'flex-start',,否则将无法工作。感谢 codedump 上的 Kerumen。那么,

var styles = StyleSheet.create({
list: {
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'flex-start',
},

其余的都是科林的回答。

按照科林 · 拉姆齐的回答。如果你想让每个项目都有一半宽度,试试这个方法。

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

我也有同样的问题,我写了一个组件来解决这个问题,你可以在这里找到它: https://github.com/pavlelekic/react-native-gridview

此外,这个组件的另一个功能是确保条目的宽度是一个整数,这样条目的边框就不会有反锯齿效果,而是清晰明了。

使用平面列表而不是 Listview 作为反应本地,它有更多的增值功能和更好的性能

ListView 现在是 不赞成,您应该改用 平面图。平面列表有一个道具称为 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} />
);
}

enter image description here

这个 博客文章很好地解释了 FlatList 的新特性。

注意: 由于某些原因,你必须在平面列表上使用 keyExtractor,而不是在每个项目上使用典型的 key道具。否则你会得到警告。基本平面列表代码抛出警告-反应本机

您可以使用 FlatList 并设置 numColumns 来获得与网格相同的结果

检查以下示例,使用 本土反应平面图组件支持具有优异性能的无限滚动:

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

这个例子看起来像

enter image description here

最好的问候,尼科尔斯

ScrollView 集装箱样式道具对我很有用

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