React Native中的ListView网格


69

我在React Native中构建了一个简单的应用程序,该应用程序从远程JSON源获取列表并将其显示在屏幕上。

到目前为止,使用此处的出色示例,我设法使用行中的ListView组件来显示结果(即每行1个结果,请参见屏幕截图)。我需要将结果显示在网格中,即每行3到6个项目,具体取决于屏幕的大小和方向。

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

这是我目前的列表显示方式-每行一个。

Answers:


127

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

我们告诉容器我们要在包装行中放置物品,并设置每个子对象的宽度。

屏幕截图


这正是我正在寻找的东西!谢谢!
Mike Driver

谢谢!这正是我所希望的,但认为并不存在。
rxb

5
在使用ListView节时,这里有人会知道如何使这项工作吗?
miki725

您将如何使每个子对象的宽度等于父容器的一半(每行两个相等大小的子对象)?我尝试了flex:.5对于带有flex:的孩子:对于父listview,有点失败。
Matt H

对于不同的身高作品?看起来像pinterest?stackoverflow.com/questions/35017978/…–
Chalist

37

现在不推荐使用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


36

我将其添加为答案,因为在Colin Ramsay的响应下隐藏了溢出注释:从React Native 0.28开始,您还需要alignItems: 'flex-start',在listview样式中使用,否则flexWrap将不起作用。感谢codedump.io上的Kerumen。所以,

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

...其余的如科林的回应。


4
这是一个重要的评论。谢谢:)
ppsreejith's

1
@kwishnu你是神!
kjonsson

我没有在codedump上回答。它在StackOverflow上;)stackoverflow.com/questions/39313268/…–
Kerumen

@kerumen-肯定!不知何故,这个问题最终出现在codedump.io/share/cSuUKROA1Mmx/1 / ...,这是我找到它的地方...无论如何,谢谢!它帮助了很多人,我对您的答案进行了投票
奎师那(Kwishnu)

@kwishnu,你是最好的
英国

7

我遇到了同样的问题,并且编写了一个解决该问题的组件,您可以在这里找到它: https //github.com/pavlelekic/react-native-gridview

另外,此组件要做的另一件事是确保项目的宽度是整数,这样项目的边框就不会出现抗锯齿,它们清晰明了。


@Pavle Lekic,感谢您编写该库。我添加了一个有关renderHeader的问题,该问题的大小没有达到完整宽度。
pmont

6

遵循Colin Ramsay的回答。而且,如果您希望每个项目的宽度都减半,请尝试这种方式。

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

我摸索了很长时间,然后才在这里绊倒你的答案。非常感谢!
Jagjot


1

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


0

使用React Native的FlatList组件检查以下示例,以出色的性能支持无限滚动:

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

这个例子看起来像

在此处输入图片说明

最好的问候,尼科尔斯


0

带有contentContainerStyle道具的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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.