【问题标题】:Render two items (images) side by side in a list view in react native在 react native 的列表视图中并排渲染两个项目(图像)
【发布时间】:2016-09-09 15:23:27
【问题描述】:

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

但我无法使用 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>
    )
}

然后根据 index 属性,我将元素左对齐或右对齐。 我的视图样式如下所示:

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

请提出一个更好的方法来做到这一点。

提前致谢。

【问题讨论】:

    标签: react-native flexbox


    【解决方案1】:

    我们过去在生产中这样做的一个好方法,并且效果很好,就是获取容器的宽度并将卡片的宽度设置为宽度的50%,然后您可以直接推将所有单个元素放入列表视图。另外,请务必设置flexWrapwrap

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

    查看下面的示例代码和示例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
    } 
    

    【讨论】:

    • 谢谢我现在正在使用它。它更简单:)
    【解决方案2】:

    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

    【讨论】:

    • @BradBumbalough 有没有人能让这个例子在模拟器上运行?我看到几乎是一个空白屏幕(一个切换元素,Big Images, Group Type + ...。图像(和其他内容)来自哪里?使用CameraRollExample.jsCameraRollView.jsAssetScaledImageExample.js 是否有参考?
    • @zipzit,是的,我以前用过这个例子。图像来自您设备的 CameraRoll 存储。您必须正确选择选项(请参阅 CameralRollExample 如何调用 CameraRollView)。随意提出一个新问题,因为这与 CameraRoll 无关。谢谢!
    • 你也可以使用 lodash 块(从 'lodash/chunk' 导入块;)
    • @EnieJakiro 对此感到抱歉。更新了!
    【解决方案3】:

    使用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,
            },
    

    就高度而言,它需要设置,但如果您没有设置高度,则可以使用“自动”。我没有进行其他测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多