使用多行React Native水平FlatList

ki1q1bka  于 2022-12-19  发布在  React
关注(0)|答案(9)|浏览(245)

我正在尝试实现一个有两行的水平滚动列表,使用FlatList,垂直滚动列表需要设置numColumns,但是没有与使用水平滚动列表的行等效的设置。
我成功地使它正确地呈现,它工作得完美无缺。但是,一个警告被抛出,说设置flexWrapVirtualizedListFlatList中不受支持,并使用numColumns。我不能使用numColumns,因为这不适用于水平列表。

<FlatList
    horizontal={true}
    contentContainerStyle={{
        flexDirection: 'column',
        flexWrap: 'wrap'
    }}
    {...otherProps}
/>

我找到了添加此警告的提交,但找不到其背后的原因。似乎没有办法在不抛出警告的情况下使其工作,至少没有完全抛弃FlatList。对于有行的水平列表有更合适的解决方案吗?

参考资料:

pkln4tw6

pkln4tw61#

请不要使用horizontal={true}。在这种情况下,您应该使用等于data长度/ 2的numColumns,并添加一个<ScrollView>标记。强制列数为总数的一半将强制列表换到下一行。

<ScrollView>
    <FlatList
        contentContainerStyle={{alignSelf: 'flex-start'}}
        numColumns={Math.ceil(listData.length / 2)}
        showsVerticalScrollIndicator={false}
        showsHorizontalScrollIndicator={false}
        data={listData}
        renderItem={({ item, index }) => {
            //push your code
        }}
    />
</ScrollView>

更新1:编辑listData.length / 2-〉Math.ceil(listData.length / 2)以下亚历克斯昂评论。

qzwqbdag

qzwqbdag2#

第一个答案,我就是这么做的:

const listData = props.data ?? [];
const numColumns = Math.ceil(listData.length / 2);
        <ScrollView
          horizontal
          showsVerticalScrollIndicator={false}
          showsHorizontalScrollIndicator={false}
          contentContainerStyle={{ paddingVertical: 20 }}>
          <FlatList
            scrollEnabled={false}
            contentContainerStyle={{
              alignSelf: 'flex-start',
            }}
            numColumns={numColumns}
            showsVerticalScrollIndicator={false}
            showsHorizontalScrollIndicator={false}
            data={listData}
            renderItem={renderItem}
          />
        </ScrollView>
vq8itlhq

vq8itlhq3#

我用简单的逻辑

<ScrollView
    horizontal
    showsHorizontalScrollIndicator={false}
    contentContainerStyle={{
        justifyContent: 'center',
        paddingHorizontal: 20,
        paddingBottom: 70,
    }}>
    <View>
        <View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
            {this.state.interest.length
                ? this.state.interest.map((d, i) => {
                    if (i % 2 == 0) {
                        return null;
                    }
                    return (
                        <Intrest
                            style={{
                                height: 40,
                                paddingHorizontal: 20,
                                alignItems: 'center',
                                justifyContent: 'center',
                                borderRadius: 30,
                                margin: 2.5,
                            }}
                            key={i}
                            data={d}
                            add={data => {
                                this._handleAddtoSelection(data);
                            }}
                            remove={data => {
                                this._handleRemoveFromSelection(data);
                            }}
                            active={this._isSelectedTopic(d)}
                        />
                    );
                })
                : null}
        </View>
        <View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
            {this.state.interest.length
                ? this.state.interest.map((d, i) => {
                    if (i % 2 != 0) {
                        return null;
                    }
                    return (
                        <Intrest
                            style={{
                                height: 40,
                                paddingHorizontal: 20,
                                alignItems: 'center',
                                justifyContent: 'center',
                                borderRadius: 30,
                                margin: 2.5,
                            }}
                            key={i}
                            data={d}
                            add={data => {
                                this._handleAddtoSelection(data);
                            }}
                            remove={data => {
                                this._handleRemoveFromSelection(data);
                            }}
                            active={this._isSelectedTopic(d)}
                        />
                    );
                })
                : null}
        </View>
    </View>
</ScrollView>

输出:Output

yhived7q

yhived7q4#

我有同样的问题与项目列表(几百),这是不是那么长,我设法克服了它,通过去我的列表Map到多个视图,每个有2个项目一个接一个(列使用flex)
如果列表不是太长,也可以使用ScrollView,它支持flexWrap

lymnna71

lymnna715#

通过一些预处理工作将每个ROWS_COUNT切片为一列

const ROWS_COUNT = 5;
const len = Math.ceil(data.length / ROWS_COUNT );
const cols = () => {
    let colsArr = Array(len);
    for (let i = 0; i < len; i++) {
        colsArr[i] = 
            <View style={styles.col}>
                {Array(ROWS_COUNT ).fill(0).map((_, j) => {
                    let index = i * ROWS_COUNT + j;
                    return (index < data.length) ? <NumSquare key={index} num={index} active={index < 23} color={"#44afff"}/> : <></>
                })}
            </View>
                    
    }
    return colsArr;
}
const colsArr = cols();

..................................

<FlatList
    horizontal
    data={colsArr}
    contentContainerStyle={styles.contentContainerStyle}
    showsVerticalScrollIndicator={false}
    showsHorizontalScrollIndicator={false}
    renderItem={({ item, index }) => item}/>

..................................

const styles = StyleSheet.create({
    col:{
        flexDirection:"column",
    }
});

结果:

klsxnrf1

klsxnrf16#

tuanngocptn的答案是可行的。然而,两行水平列表也可以在水平拖动的同时垂直拖动,这并不是一个很好的UX。
directionalLockEnabled={true}alwaysBounceVertical={false}添加到ScrollView将解决此问题

<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
directionalLockEnabled={true}
alwaysBounceVertical={false}
>
    <FlatList
        ...
    />
</ScrollView>
xesrikrc

xesrikrc7#

我发现的最简单的方法(如果您想要x列,请更改numColumns以将数据长度除以x):

return (
    <ScrollView horizontal={true} showsVerticalScrollIndicator={false} showsHorizontalScrollIndicator={false} >
      <FlatList
        data = {yourData}
        renderItem={renderFunction}
        numColumns={Math.ceil(yourData.length / 2)}
        scrollEnabled={false}
        />
    </ScrollView>
  )
moiiocjp

moiiocjp8#

我使用numRows属性为FlatList创建了一个 Package 器。
该解决方案没有在ScrollView中使用FlatList,因为这可能会使FlatList的一些性能优化无效。相反,它将数据分块并添加也可以设置样式的列组件。
https://www.npmjs.com/package/@idiosync/horizontal-flatlist

byqmnocz

byqmnocz9#

让我们检查一下:https://snack.expo.dev/@legiaquan/flatlist-extra-expo?platform=android附加平面列表:https://www.npmjs.com/package/flatlist-extra

import { Text, View, StyleSheet } from 'react-native';
import { FlatListExtra } from 'flatlist-extra';

export default function App() {
  const data = [
    { idItem: 1, name: 'one' },
    { idItem: 2, name: 'two' },
    { idItem: 3, name: 'three' },
    { idItem: 4, name: 'four' },
    { idItem: 5, name: 'five' },
    { idItem: 6, name: 'six' },
    { idItem: 7, name: 'seven' },
    { idItem: 8, name: 'eight' },
    { idItem: 9, name: 'nine' },
  ];
  const renderItem = ({ item }) => (
    <View style={{ width: 100, height: 100, borderWidth: 1 }}>
      <Text
        style={{
          alignSelf: 'center',
        }}>
        {item.name}
      </Text>
    </View>
  );
  return (
    <FlatListExtra
      data={data}
      renderItem={renderItem}
      showsHorizontalScrollIndicator={false}
      horizontal
      numRows={2}
      id={'idItem'}
    />
  );
}

相关问题