反应本机 FlatList 与列,最后一项宽度

React Native FlatList with columns, Last item width

我正在使用 FlatList 在两列中显示项目列表

<FlatList style={{margin:5}}
  data={this.state.items}
  numColumns={2}
  keyExtractor={(item, index) => item.id }
  renderItem={(item) => <Card image={item.item.gallery_image_url} text={item.item.name}/> }
/>

卡片组件只是一个带有一些样式的视图:

<View style={{ flex: 1, margin: 5, backgroundColor: '#ddd', height: 130}} ></View>

它工作正常,但如果项目的数量是奇数,最后一行只包含一个项目并且该项目延伸到屏幕的整个宽度。

如何将项目设置为与其他项目相同的宽度?

您可以在此处尝试一些操作。

A) 为卡片设置预定义的宽度(可能等于您设置的高度?)。然后,您可以使用 alignItems 将卡片放置在中间或左侧 - 不确定您在这里想要哪个。

B) 如果有偶数张卡片,您可以在末尾添加一个空视图以填充此 space。我发现此方法非常笨拙,但在尝试为将来的元素保留 space 时很有用。

C) 只需使用 alignItems: 'space-between,我喜欢用它来居中项目,但你必须定义宽度,或者使用类似 flex:0.5

的东西

我建议对 flexbox 进行更多研究以帮助您解决这个问题,因为很难说出这种情况的上下文。我假设上述方法会有所帮助,但如果没有,这里有一些链接供您查看 -

First link

Second link

Third linkLink破

希望这对您有所帮助。如果您需要任何进一步的说明 - 请询问

您可以尝试通过 Dimensions 获取设备的当前宽度,根据您要呈现的列数进行一些计算,减去边距并将其设置为 minWidth 和 maxWidth。

例如:

const {height, width} = Dimensions.get('window');
const itemWidth = (width - 15) / 2;

<View style={{ flex: 1, margin: 5, backgroundColor: '#ddd', minWidth: {this.itemWidth}, maxWidth: {this.itemWidth}, height: 130}} ></View>

对于你的情况使用 flex: 1/2

因此:您的 item 应该有 flex of 1/(number of columns) 如果你有 3 列你的项目应该有 flex:1/3

原因是你的 Card 有样式 flex: 1,所以它会尝试扩展所有 space 的剩余部分。 您可以通过将 maxWidth: '50%' 添加到您的 Card style

来修复它
<View style={{ flex: 1, margin: 5, backgroundColor: '#ddd', height: 130, maxWidth: '50%'}} ></View>

这是使用列和均匀间隔设置 FlatList 样式的最干净的方法:

    <FlatList style={{margin:5}}
        numColumns={2}                  // set number of columns 
        columnWrapperStyle={style.row}  // space them out evenly
        
        data={this.state.items}
        keyExtractor={(item, index) => item.id }
        renderItem={(item) => <Card image={item.item.gallery_image_url} text={item.item.name}/> }
    />       

    const style = StyleSheet.create({
        row: {
            flex: 1,
            justifyContent: "space-around"
        }
    });

@Emilius Mfuruki 的建议很好,但如果您的文本长度不同,则效果不佳。然后在项目视图中使用此宽度:

const {height, width} = Dimensions.get('window');
const itemWidth = (width - (MarginFromTheSide * 2 + MarginInBetween * (n-1))) / n;

在 FlatList 中使用:

columnWrapperStyle={{
            flex: 1,
            justifyContent: 'space-evenly',
          }}

完美运行。

您可以使用 ListFooterComponent={this.renderFooter}

只需使用 flex:0.5 和宽度:'50%'

创建一个包含奇数张图片的数组,例如:

const images = [
  require('./../...jpg'),
  require('./../...jpg'),
  require('./../...jpg'),
  require('./../...jpg'),
  require('./../...jpg'),
];

然后,使用下面给出的代码,

const App = () => {
const _renderItem = ({ item, index }) => (
  <Image
    source={item}
    style={{
      width: '50%',
      height: 200,
    }}
    resizeMode="cover"
  />
 );

return (
    <View style={{flex: 1, marginHorizontal: 10,}}>
      <FlatList
        columnWrapperStyle={{ justifyContent: 'space-between' }}
        keyExtractor={(_, index)=> index.toString()}
        data={images}
        numColumns={2}
        renderItem={_renderItem}
      />
    </View>
  )
};
export default App;

Working Example

我尝试了上面的一些解决方案,但最后一项(2 列列表)的边距仍然存在一些问题。

我的解决方案是简单地将项目包装到父容器中,将原始容器保留为 flex: 1,将项目的父容器保留为 flex: 0.5,这样它就会正确地占用边距。

itemContainer: {
  flex: 0.5,
},
itemSubContainer: {
  flex: 1,
  marginHorizontal: margin,
},

最简单的解决方案是计算一下。 想象一下,我们每行有 2 个视图,我们想给每边 10 个边距,它看起来像这样:

如上图所示,每个视图在水平方向上都有 2 个边距。 (红色矩形内) 所以我们必须从宽度中减去边距、列数和 2 的乘积。

import { Dimensions } from 'react-native';
const {width} = Dimensions.get("window")
const column = 2
const margin = 10
const SIZE = (width - (margin * column * 2)) / column
<View style={{ margin: 10, width: SIZE }} ></View>

我也遇到了同样的问题

所以,你可以使用这个 package

默认情况下可以防止那个问题和其他一些问题

安装:

npm install grid-flatlist-react-native

用法:

import GridFlatList from 'grid-flatlist-react-native';

<GridFlatList
  data={[1,2,3,4,5,6]}
  renderItem={(item) => (<Text>{item}</Text>)}
  gap={10} // spacing between items
  paddingHorizontal={10} // shadow around elements will not be clipped
/>