You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中Staggered Grid网格项重叠问题解决求助

解决SwiftUI交错网格(Staggered Grid)项重叠问题

你的交错网格出现重叠的核心原因是错误使用了LazyVGrid布局:LazyVGrid是基于行的布局系统,每行的高度由该行最高的元素决定,当你给网格项设置随机高度时,高度较小的项下方会被下一行的元素覆盖。此外,你实现的setUpList方法已经将数据拆分为多列数组,但在body中并未实际使用这个拆分后的结构,而是直接遍历整个数据源,这完全违背了交错网格(瀑布流)的布局逻辑。

解决方案:改用列独立垂直布局

正确的交错网格应该是将数据按列拆分,然后用HStack包裹多个VStack,每个VStack对应一列的内容,让每列的元素独立垂直排列,这样不同高度的元素就不会跨列重叠。

修改后的完整代码

1. 修复StaggeredGrid结构

struct StaggeredGrid<Content: View,T:Identifiable>: View where T: Hashable{
        
    // MARK: - Properties
    var content: (T) -> Content
    var list: [T]
    var columns: Int
    var showIndicators:Bool
    var spacing: CGFloat
    
    init(list: [T], columns: Int, showIndicators: Bool = false, spacing: CGFloat = 10,@ViewBuilder content: @escaping (T) -> Content) {
        self.content = content
        self.list = list
        self.columns = columns
        self.showIndicators = showIndicators
        self.spacing = spacing
    }
    
    func setUpList() -> [[T]]{
        var gridArray: [[T]] = Array(repeating: [], count: columns)
        var currentIndex:Int = 0
        for object in list{
            gridArray[currentIndex].append(object)
            currentIndex = (currentIndex + 1) % columns // 简化索引切换逻辑
        }
        return gridArray
    }
    
    // MARK: - Body
    var body: some View {
        ScrollView(.vertical,showsIndicators: showIndicators){
            HStack(alignment: .top, spacing: spacing) {
                ForEach(setUpList(), id: \.self) { columnItems in
                    VStack(spacing: spacing) {
                        ForEach(columnItems, id: \.id) { item in
                            content(item)
                        }
                    }
                }
            }
            .padding()
        }
    }
}

2. 优化PhotoGridItem布局

移除不必要的GeometryReader,让元素自然适应列宽:

struct PhotoGridItem: View {
    var photo: Photo
    var body: some View {
        VStack(spacing: 10) {
            AsyncImage(url: URL(string: photo.imagePath)) { image in
                image
                    .resizable()
                    .scaledToFill()
            } placeholder: {
                Color.gray.opacity(0.1)
            }
            .frame(maxWidth: .infinity)
            .clipped()

            Text(photo.title)
                .font(.headline)
                .frame(height: 80)
                .frame(maxWidth: .infinity, alignment: .leading)
        }
        .cornerRadius(10)
        .background(Color.white)
        .shadow(radius: 3)
        .frame(height: CGFloat.random(in: 130...170), alignment: .top)
    }
}

关键修改说明

  1. 使用拆分后的列数据:setUpList方法生成的多列数组现在被实际用于布局,每列对应一个VStack,保证元素在各自列内垂直排列。
  2. HStack对齐方式:设置alignment: .top让所有列的顶部对齐,确保布局整齐。
  3. 移除冗余布局约束:去掉PhotoGridItem中的GeometryReader,改用maxWidth: .infinity让内容自动填充列宽,避免不必要的布局冲突。
  4. 简化索引逻辑:用取模运算currentIndex = (currentIndex + 1) % columns替代原有的条件判断,代码更简洁健壮。

内容的提问来源于stack exchange,提问作者Dhiru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 13:55:03