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

SwiftUI中如何实现带横竖连续分隔线的分页网格视图

SwiftUI实现带连续横竖分隔线的分页网格视图解决方案

问题说明

需要实现带有连续横向和纵向分隔线的分页网格视图,要求两行网格项高度一致,当前代码通过缩小第二行高度的取巧方式无法满足需求,需采用更可靠的实现方案。

最佳实现方案

核心思路是将分隔线与网格项解耦,通过自定义背景视图统一绘制完整的分隔线,而非在每个网格项内部添加分隔线。这样既能保证两行高度一致,又能让分隔线连续无断裂。

完整代码

struct ContentView: View {
    // 统一设置两行网格高度为90
    let rows = [GridItem(.fixed(90)), GridItem(.fixed(90))]
    // 每页显示4列网格项
    let columnsPerPage = 4
    // 单个网格项的尺寸
    let itemSize = CGSize(width: 80, height: 80)
    
    var body: some View {
        TabView {
            pageView(startIndex: 0)
            pageView(startIndex: 8)
        }
        .tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
    }
    
    func pageView(startIndex: Int) -> some View {
        ScrollView(.horizontal, showsIndicators: false) {
            LazyHGrid(rows: rows, spacing: 0) {
                ForEach(startIndex..<startIndex+8, id: \.self) { index in
                    // 仅放置网格内容,分隔线统一由背景视图处理
                    RoundedRectangle(cornerRadius: 10)
                        .fill(Color.blue)
                        .frame(width: itemSize.width, height: itemSize.height)
                }
            }
            // 添加自定义分隔线背景
            .background(
                GridDividers(rows: rows.count, columns: columnsPerPage, itemSize: itemSize, lineWidth: 2, lineColor: .gray)
            )
            .padding(.horizontal)
        }
    }
}

// 自定义视图:绘制网格的横竖分隔线
struct GridDividers: View {
    let rows: Int
    let columns: Int
    let itemSize: CGSize
    let lineWidth: CGFloat
    let lineColor: Color
    
    var body: some View {
        GeometryReader { geo in
            ZStack(alignment: .topLeading) {
                // 绘制纵向分隔线:每两列之间一条
                ForEach(1..<columns) { colIndex in
                    Rectangle()
                        .fill(lineColor)
                        .frame(width: lineWidth)
                        .offset(
                            x: itemSize.width * CGFloat(colIndex) + lineWidth * CGFloat(colIndex - 1),
                            y: 0
                        )
                        .frame(height: geo.size.height)
                }
                
                // 绘制横向分隔线:两行之间一条
                ForEach(1..<rows) { rowIndex in
                    Rectangle()
                        .fill(lineColor)
                        .frame(height: lineWidth)
                        .offset(
                            x: 0,
                            y: itemSize.height * CGFloat(rowIndex) + lineWidth * CGFloat(rowIndex - 1)
                        )
                        .frame(width: geo.size.width)
                }
            }
        }
    }
}

方案解析

  1. 统一网格高度:将两行GridItem的高度都设置为90,避免取巧式的高度调整。
  2. 分隔线解耦:通过GridDividers自定义视图在网格背景绘制分隔线,确保分隔线是独立于网格项的完整线条。
  3. 精确位置计算:利用GeometryReader获取网格的实际尺寸,结合网格项尺寸和分隔线宽度,精确计算每条分隔线的偏移位置,保证线条连续对齐。
  4. 扩展性强:如果需要调整网格项尺寸、分隔线宽度或颜色,只需修改对应参数即可,无需修改网格项的布局逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:12:03