【问题标题】:React Native FlatList with columns, Last item widthReact Native FlatList with columns, Last item width
【发布时间】:2017-09-16 02:37:53
【问题描述】:

我正在使用 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>

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

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

【问题讨论】:

    标签: react-native react-native-flatlist


    【解决方案1】:

    根据您的情况使用 flex: 1/2

    因此:如果您有 3 列,您的 item 应该有 flex 1/(列数),那么您的项目应该有 flex:1/3

    【讨论】:

    • 不确定为什么没有将其标记为答案。这是最简单正确的解决方案!
    • 当我给 flex: 1/2 时,最后一个项目的宽度比前面的项目大,请问我们如何解决这个问题
    • 天才!!!这行得通!有史以来最好的解决方法。谢谢你,你应该得到正确的答案
    • 我试过这个,就像“iOSDev”所说,最后一行的单个项目比前一行的第一个项目略宽。因此这个解决方案对我不起作用
    • 最后一行稍宽的问题可能与边距有关;尝试将项目包装在没有边距的视图中。
    【解决方案2】:

    您可以在这里尝试一些事情。

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

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

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

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

    First link

    Second link

    Third link 链接中断

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

    【讨论】:

    • B 是一个合理的 hack。选项 A 是多余的,可以通过添加 flexWrap 简单地设置为对齐。在这种情况下,numColumns 的目的是什么?
    • 我不愿意选择 B,但我做到了,虽然这是一个 hack,但它工作得很好,而且我不必指定元素的宽度(我希望它们适应可用宽度)
    • @Ryan :我想要第一个单元格完全拉伸并有 3 列,我该怎么办??
    • 选项 C:设置 Flex:0.5 适合我。
    【解决方案3】:

    您可以尝试通过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
    • 非常好。谢谢!
    • 出现错误:属性“样式”的类型不兼容
    • @Ghost 你在用打字稿吗?如果是这样,则该错误可能与 Typescript 有关
    【解决方案4】:

    这是使用列和均匀间隔设置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"
            }
        });
    

    【讨论】:

    • 当列数为 3 时,这将无法按预期工作,如果总项目数是 5 的倍数,您将看到最后一行之间的空白空间。
    【解决方案5】:

    原因是你的卡片有flex: 1的样式,所以它会尝试扩展所有剩余的空间。 您可以通过将maxWidth: '50%' 添加到您的卡片样式来修复它

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

    【讨论】:

    • 有史以来最简单的解决方案
    【解决方案6】:

    @Emilius Mfuruki 的建议很好,但如果您有不同长度的文本,它就不能完美地工作。然后在你的项目视图中使用这个宽度:

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

    在 FlatList 中使用:

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

    完美运行。

    【讨论】:

    • 我做了类似的事情。澄清一下,MarginFromTheSide 是屏幕水平边距,而MarginInBetween 是每列之间的边距。所以你得到了FlatList 的可用宽度,删除边距并将它除以列的数量,这样你就有了每个项目的宽度:)
    • 说真的,我以前从未见过这个 columnWrapperStyle,(我有点责备我)但大多数标准列教程都试图对列逻辑进行硬编码...。感谢提示
    【解决方案7】:

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

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

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

    【讨论】:

      【解决方案8】:

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

      【讨论】:

        【解决方案9】:

        只需使用 flex:0.5 和 width:'50%'

        【讨论】:

          【解决方案10】:

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

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

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

          const App = () => {
          const _renderItem = ({ item, index }) => (
            <Image
              source={item}
              style={{
                width:
                  images.length % 2 !== 0 && images.length - 1 === index
                    ? '100%'
                    : '50%',
                height: 200,
              }}
              resizeMode="cover"
            />
           );
          
          return (
              <View style={{flex: 1, marginHorizontal: 10,}}>
                <FlatList
                  columnWrapperStyle={{ justifyContent: 'space-between' }}
                  data={images}
                  numColumns={2}
                  renderItem={_renderItem}
                />
              </View>
            )
          };
          export default App;
          

          Working Example

          【讨论】:

            猜你喜欢
            • 2019-05-08
            • 1970-01-01
            • 2022-11-03
            • 2021-09-09
            • 2022-01-16
            • 2018-04-05
            • 2018-06-04
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多