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

SwiftUI中LazyVGrid实现自适应均匀间距布局的技术问询

SwiftUI 实现自适应间距的4列网格布局

核心思路

系统默认的网格组件(比如LazyVGrid)没法同时满足「部分行居中不填满、部分行填满整行」的混合需求,所以我们可以把数据按最多4个元素一组拆分,再针对每组的元素数量,用HStack结合Spacer实现对应布局:

  • 1个元素:左右加Spacer让元素居中
  • 2/3个元素:左右和元素之间都加Spacer,保证元素均匀分布且整体居中,不拉伸元素宽度
  • 4个元素:仅在元素之间加Spacer,让元素填满整行

完整代码实现

首先给数组加个分组扩展,方便按4个元素拆分:

extension Array {
    func chunked(into size: Int) -> [[Element]] {
        return stride(from: 0, to: count, by: size).map {
            Array(self[$0..<Swift.min($0 + size, count)])
        }
    }
}

然后实现自定义的自适应网格视图:

struct AdaptiveGridView<Content: View, Item: Identifiable>: View {
    let items: [Item]
    let content: (Item) -> Content
    let spacing: CGFloat
    
    init(items: [Item], spacing: CGFloat = 16, @ViewBuilder content: @escaping (Item) -> Content) {
        self.items = items
        self.spacing = spacing
        self.content = content
    }
    
    var body: some View {
        LazyVStack(spacing: spacing) {
            ForEach(items.chunked(into: 4), id: \.self) { rowItems in
                switch rowItems.count {
                case 1:
                    HStack {
                        Spacer()
                        content(rowItems[0])
                        Spacer()
                    }
                case 2, 3:
                    HStack(spacing: spacing) {
                        Spacer()
                        ForEach(rowItems) { item in
                            content(item)
                            if item != rowItems.last {
                                Spacer()
                            }
                        }
                        Spacer()
                    }
                case 4:
                    HStack(spacing: spacing) {
                        ForEach(rowItems) { item in
                            content(item)
                            if item != rowItems.last {
                                Spacer()
                            }
                        }
                    }
                default:
                    EmptyView()
                }
            }
        }
        // 可选:给整个网格加外层内边距
        .padding()
    }
}

使用示例

// 定义数据模型
struct GridItemModel: Identifiable {
    let id: Int
    let text: String
}

struct ContentView: View {
    // 测试数据
    let testItems = [
        GridItemModel(id: 1, text: "Cell 1"),
        GridItemModel(id: 2, text: "Cell 2"),
        GridItemModel(id: 3, text: "Cell 3"),
        GridItemModel(id: 4, text: "Cell 4"),
        GridItemModel(id: 5, text: "Cell 5"),
        GridItemModel(id: 6, text: "Cell 6"),
        GridItemModel(id: 7, text: "Cell 7")
    ]
    
    var body: some View {
        AdaptiveGridView(items: testItems) { item in
            // 自定义每个单元格的样式
            Text(item.text)
                .padding(.vertical, 12)
                .padding(.horizontal, 24)
                .background(Color.gray.opacity(0.2))
                .cornerRadius(8)
        }
    }
}

效果说明

  • 1个元素:单元格居中显示,宽度为自身内容宽度
  • 2/3个元素:单元格均匀分布且整体居中,元素之间的间距与到屏幕边缘的间距一致,不拉伸单元格宽度
  • 4个元素:单元格填满整行,元素之间间距均匀
  • 第5个及以后的元素自动换行,行与行之间的间距和单元格间距保持一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:53:11