【问题标题】:Two columns in RN FlatListRN FlatList 中的两列
【发布时间】:2018-06-28 01:14:24
【问题描述】:

如何在 React Native Flatlist 中列出 2 列,例如:

【问题讨论】:

  • 您是否正在尝试可变高度布局?另外,你做了什么来解决这个问题?还有其他类似的问题有答案,但我不知道有什么不同,因为你的细节太少了。见How To Ask
  • “可变高度布局”没有区别。 "numColumns" 创建一个网格。

标签: react-native react-native-flatlist


【解决方案1】:

你可以试试react-native-scroll-lazy,而不是ScrollView,之前遇到过类似的问题,我已经解决了,写了一个库分享给有同样问题的人。

【讨论】:

【解决方案2】:

我花了很长时间才弄清楚这一点,但这实际上可以在不使用任何外部库的情况下实现。诀窍是使用负边距。

将在 VirtualizedList 属性 CellRendererComponent 中应用负边距,以使其在 Android 上正常工作。

JSX:

<View style={styles.container}>
      <FlatList
        style={styles.flatlist}
        data={data}
        keyExtractor={(item, index) => index.toString()}
        CellRendererComponent={({ children, item, ...props }) => {
            return (
                <View {...props} style={{ marginTop: item.marginTop }}>
                    {children}
                </View>
            )
        }}
        renderItem={({ item }) => {
            const { source: source1, height: height1, marginTop: marginTop1 } = item.image1;
            const { source: source2, height: height2, marginTop: marginTop2 } = item.image2;
            return (
                <View style={Style.viewRow}>
                    <Image source={source1} style={[styles.image, { height: height1, marginTop: marginTop1 }]} />
                    <Image source={source2} style={[styles.image, { height: height2, marginTop: marginTop2 }]} />
                </View>
            )
        }}
    />
</View>

数据:

const source = { uri: 'https://placekitten.com/160/300' };

const data = [
    {
        marginTop: 0,
        image1: { source, height: 300, marginTop: 0 },
        image2: { source, height: 250, marginTop: 0 }
    },
    {
        marginTop: -50,
        image1: { source, height: 290, marginTop: 50 },
        image2: { source, height: 300, marginTop: 0 }
    },
    {
        marginTop: -40,
        image1: { source, height: 250, marginTop: 40 },
        image2: { source, height: 350, marginTop: 0 }
    }
];

样式:

const styles = StyleSheet.create({
   container: {
      flex: 1
   },
   flatList: {
      width: '100%',
      height: '100%'
   },
   viewRow: {
      flexDirection: 'row'
   },
   image: {
      width: '50%',
      resizeMode: 'cover'
   }
});

请注意,正确排列数组中的图像取决于您 - 始终将较高的图像放在较短的一侧,并确保计算高度差并跟踪它。玩得开心。

【讨论】:

    【解决方案3】:

    通过numColumns

    <FlatList 
     data={albums}
     renderItem={({item}) => <></>}
     numColumns={2}
    />
    

    【讨论】:

      【解决方案4】:

      只需将 prop numColumns 传递给您的 FlatList 组件。

      【讨论】:

      • 我也是这么想的,但是当我阅读道具时,我看到了这一点:项目都应该是相同的高度 - 不支持砖石布局。 看起来像 OP正在尝试这样的布局,所以除非有一些可以完成的样式技巧,否则这将不起作用。
      • @MichaelCheng 虽然示例图像具有不同的高度,但问题中没有提到它需要具有不同的高度,它只是询问如何在 FlatList 组件中获取两列。我认为问题作者不知道这个道具。
      • 同意。我会标记和评论以要求澄清。
      • "numColumns" 创建一个网格。
      • 自我注意:制作内部物品flex:1会填满宽度
      【解决方案5】:

      您可以通过以下两种方式之一进行操作。首先,直接的方法是创建 2 个具有 flex 布局的 FlatList 列,并在它们之间分配数据,如下所示:

      假设您定义了 styledata

      const style={
        container: {
          flex: 1,
          flexDirection: 'row',
          height: 400
        },
        column: {
          flex: 1,
          flexDirection: 'column'
        },
        row: {
          flexDirection: 'row'
        },
        item: {
          flex: 1
        }
      }
      
      const data = [
        { key: 'A' },
        { key: 'B' },
        { key: 'C' },
        { key: 'D' },
        { key: 'E' },
        { key: 'F' },
        { key: 'G' },
        { key: 'H' },
        { key: 'I' }
      ];
      

      你可以这样做

      render() {
        //Split the data (however you want it)
        const column1Data = data.filter((item, i) => i%2 === 0);
        const column2Data = data.filter((item, i) => i%2 === 1);
      
        return (
          <View style={ style.container }>
      
            <View style={ style.column }>
              <Text>Column 1</Text>
              <FlatList
                data={ column1Data }
                renderItem={ ({ item }) => (
                  <View style={ style.item }>
                    <Text>{ item.key }</Text>
                  </View>
                ) }
              />
            </View>
      
            <View style={ style.column }>
              <Text>Column 2</Text>
              <FlatList
                data={ column2Data }
                renderItem={ ({ item }) => (
                  <View style={ style.item }>
                    <Text>{ item.key }</Text>
                  </View>
                ) }
              />
            </View>
      
          </View>
        );
      }
      

      问题是这两个列表是独立的,会带来糟糕的移动体验。更好的方法是将您的数据分组并呈现单列 FlatList,以便统一您的内容。

      首先您需要一个函数将您的数据分组为“行”数据

        //The key here is grouping the data to be in one row together
        const groupData = (items, groupLen) => {
          const groups = [];
          let i = 0;
      
          while (i < items.length) {
            groups.push(items.slice(i, i += groupLen));
          }
      
          return groups;
        };
      

      那就这样吧……

      render() {
        const groupedItems = groupData(data, 2)
      
        return (
          <View style={ style.column }>
      
              <Text>Main Column</Text>
              <FlatList
                data={ groupedItems }
                renderItem={ ({ item }) => (
                  <View style={ style.row }>
                    {
                      /* item is really the group of items in the row */
                      item.map((singleItem, index ) => (
                        <Text style={ style.item }>{ singleItem.key }</Text>
                      ))
                    }
                  </View>
                ) }
              />
      
          </View>
        );
      }
      

      你可能需要摆弄样式才能得到你想要的,但你明白了:)

      【讨论】:

      • FlatList 不支持像 OP 的问题那样高度不同的项目。
      【解决方案6】:

      react-native 中的标准样式是flexDirection: 'col',这意味着元素是从上到下排列的。要更改此设置(从右到左),您应该将样式设置为 flexDirection: 'row'

      <View style={{flexDirection: 'row'}}>
        <FlatList
          data={[{key: 'a'}, {key: 'b'}]}
          renderItem={({item}) => <Text>{item.key}</Text>}
        />
        <FlatList
          data={[{key: 'a'}, {key: 'b'}]}
          renderItem={({item}) => <Text>{item.key}</Text>}
        />
      </View>
      

      【讨论】:

        猜你喜欢
        • 2022-12-16
        • 2020-01-22
        • 2020-12-05
        • 2021-02-04
        • 1970-01-01
        • 2022-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多