在本地反应列表视图中并排渲染两个项目(图像)

时间:2016-05-13 12:15:37

标签: react-native flexbox

我正在尝试设计类似以下屏幕截图的内容。 请注意,每个磁贴都是从后端获取的Product元素。

Product tiles

但我无法使用ListView及其renderRow方法执行此操作,该方法拒绝使用任何类型的InfiniteScroll组件。

目前我正在运行一个包含2个元素的循环,并在滚动视图中渲染2个元素。以下是我的代码,以便更好地解释。

render() {
    var elem = [];
    for(var i = 0; i < this.state.products.length; i+=2) {
      var prod = this.state.products[i];
      var prod2 = this.state.products[i + 1];
      elem.push(
        <View style={styles.view} key={i} >
          <ProductTile onPressAction={this._pdpPage} prod={prod} index={i} />
          <ProductTile onPressAction={this._pdpPage} prod={prod2} index={i + 1} />
        </View>
      );
    }
    return (
        <ScrollView>
          {elem}
        </ScrollView>
    )
}

然后根据索引道具我左右对齐元素。 我的视图样式如下所示:

view: {
  flex: 1,
  flexDirection: 'row',
},

请建议更好的方法。

提前致谢。

3 个答案:

答案 0 :(得分:14)

我们过去在生产中做到这一点的一个好方法,它已经很好,是为了获得容器的宽度并将卡片的宽度设置为宽度的50%,然后你可以推所有单个元素都进入listview。另外,请务必设置flexWrap wrap

这适用于所有设备尺寸,不需要额外的模块或库。

查看下面的示例代码和示例here

https://rnplay.org/apps/t_6-Ag

/* Get width of window */
const width = Dimensions.get('window').width

/* ListView */
<ListView
  contentContainerStyle={styles.listView}
  dataSource={this.state.dataSource}
  renderRow={this.renderRow.bind(this)}
/>

/* Row */
renderRow () {
  return <View style={styles.card}>
           <Text>{rowData.name} {rowData.price}</Text>
         </View>

/* Styles */
listView: {
  flexDirection: 'row',
  flexWrap: 'wrap'
},
card: {
  backgroundColor: 'red',
  width: (width / 2) - 15,
  height: 300,
  marginLeft: 10,
  marginTop: 10
} 

答案 1 :(得分:7)

React Native在他们的CameraRollView.js示例中有一个很好的例子。他们使用名为groupByEveryN的库来允许您设置每行要渲染的项目数。

请注意您对ListView.DataSource ...

的启动方式的更改
var ds = new ListView.DataSource({rowHasChanged: this._rowHasChanged});
  this.state.dataSource = ds.cloneWithRows(
    groupByEveryN(this.state.assets, this.props.imagesPerRow)
  );

您的renderRow函数只需要预期一系列项目......

// rowData is an array of images
_renderRow: function(rowData: Array<Image>, sectionID: string, rowID: string)  {
  var images = rowData.map((image) => {
    if (image === null) {
      return null;
    }  
    return this.props.renderImage(image);
  });

  return (
    <View style={styles.row}>
      {images}
    </View>
  );
}

此处的完整示例文件:https://github.com/facebook/react-native/blob/a564af853f108e071e941ac08be4cde864f5bfae/Examples/UIExplorer/js/CameraRollView.js

答案 2 :(得分:0)

使用https://facebook.github.io/react-native/docs/flexbox作为基准,通过添加flexWrap:'wrap',我已经可以在我的项目中轻松做到这一点。

        `<View style={{flex: 1, flexDirection: 'row', flexWrap: 'wrap'}}>
            <View style={{height: 150, width: '50%', backgroundColor: 'powderblue'}} />
            <View style={{height: 150, width: '50%', backgroundColor: 'skyblue'}} />
            <View style={{height: 150, width: '50%', backgroundColor: 'steelblue'}} />
            <View style={{height: 150, width: '50%', backgroundColor: 'powderblue'}} />
            <View style={{height: 150, width: '50%', backgroundColor: 'skyblue'}} />
            <View style={{height: 150, width: '50%', backgroundColor: 'steelblue'}} />
        </View>`

所以在您的项目中

         render() {
            var elem = [];
            for(var i = 0; i < this.state.products.length; i+=2) {
            var prod = this.state.products[i];
            var prod2 = this.state.products[i + 1];
            elem.push(
                <View style={styles.view} key={i} >
                <ProductTile onPressAction={this._pdpPage} prod={prod} index={i} />
                <ProductTile onPressAction={this._pdpPage} prod={prod2} index={i + 1} />
                </View>
            );
            }

        return (
            <ScrollView>
                <View style={{flex: 1, flexDirection: 'row', flexWrap: 'wrap'}}>
                    {elem}
                </View>
            </ScrollView>
            )
        }

        view: {
          width: '50%',
          height: 150,
        },

就高度而言,需要进行设置,但是如果您没有设置高度,则可以与“自动”一起使用。否则我没有测试。