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

SwiftUI复杂布局问题:选用哪种网格系统实现百分比分配?

SwiftUI 按百分比分配空间的网格布局方案选择

我写了下面这段SwiftUI代码:

struct MapPinSheetMoreInfoView: View {
    let item: Place
    var body: some View {
        HStack(alignment: .top, spacing: 3) {
            VStack(alignment: .leading) {
                Text("Location")
                    .font(.caption.weight(.semibold))
                    .lineLimit(1)
                if item.address != "" {
                    Text(item.address)
                        .font(.footnote)
                        .foregroundColor(.secondary)
                    Text(item.city + ", " + item.state)
                        .font(.footnote)
                        .foregroundColor(.secondary)
                } else {
                    Text("N/A")
                }
            }
            Divider()
            VStack(alignment: .leading) {
                HStack {
                    VStack {
                        Text("Weather")
                            .font(.caption.weight(.semibold))
                            .lineLimit(1)
                        HStack(alignment: .firstTextBaseline, spacing: 3) {
                            Image(systemName: "waveform")
                                .imageScale(.small)
                                .foregroundColor(.secondary)
                            Text("79%")
                                .font(.caption.weight(.regular))
                                .foregroundColor(.secondary)
                        }
                    }
                    Divider()
                    HStack {
                        Text("Hello, World!")
                    }
                }
                Divider()
                HStack {
                    HStack {
                        Text("Hello, World!")
                    }
                    Divider()
                    HStack {
                        Text("Hello, World!")
                    }
                }
            }
        }
    }
}

当前代码的布局存在错位问题,我希望实现能让视图按固定百分比分配空间的网格布局,请问应该选用哪种网格系统?


推荐两种可行方案

1. 原生首选:Grid(iOS 16+、macOS 13+)

Grid是SwiftUI在iOS16之后推出的原生网格布局,支持通过gridCellColumns设置列宽比例,完全满足固定百分比分配的需求,代码简洁易维护。

修改后的示例代码:

struct MapPinSheetMoreInfoView: View {
    let item: Place
    var body: some View {
        Grid(alignment: .topLeading, horizontalSpacing: 3, verticalSpacing: 3) {
            GridRow {
                // 左侧区域:占总宽度1/3(对应30%左右比例)
                VStack(alignment: .leading) {
                    Text("Location")
                        .font(.caption.weight(.semibold))
                        .lineLimit(1)
                    if item.address != "" {
                        Text(item.address)
                            .font(.footnote)
                            .foregroundColor(.secondary)
                        Text(item.city + ", " + item.state)
                            .font(.footnote)
                            .foregroundColor(.secondary)
                    } else {
                        Text("N/A")
                    }
                }
                .gridCellColumns(1)

                Divider()

                // 右侧区域:占总宽度2/3(对应70%左右比例),内部再拆分为两列
                Grid(alignment: .topLeading, horizontalSpacing: 3) {
                    GridRow {
                        VStack(alignment: .leading) {
                            Text("Weather")
                                .font(.caption.weight(.semibold))
                                .lineLimit(1)
                            HStack(alignment: .firstTextBaseline, spacing: 3) {
                                Image(systemName: "waveform")
                                    .imageScale(.small)
                                    .foregroundColor(.secondary)
                                Text("79%")
                                    .font(.caption.weight(.regular))
                                    .foregroundColor(.secondary)
                            }
                        }
                        .gridCellColumns(1)

                        Divider()

                        Text("Hello, World!")
                            .frame(maxWidth: .infinity, alignment: .leading)
                            .gridCellColumns(1)
                    }

                    Divider()

                    GridRow {
                        Text("Hello, World!")
                            .frame(maxWidth: .infinity, alignment: .leading)
                            .gridCellColumns(1)

                        Divider()

                        Text("Hello, World!")
                            .frame(maxWidth: .infinity, alignment: .leading)
                            .gridCellColumns(1)
                    }
                }
                .gridCellColumns(2)
            }
        }
    }
}

2. 兼容旧系统:GeometryReader + 手动百分比宽度

如果需要支持iOS15及更早版本,可以用GeometryReader获取父视图的宽度,直接给子视图设置百分比宽度,实现固定比例分配。

示例代码:

struct MapPinSheetMoreInfoView: View {
    let item: Place
    var body: some View {
        GeometryReader { geo in
            HStack(alignment: .top, spacing: 3) {
                // 左侧占30%宽度
                VStack(alignment: .leading) {
                    Text("Location")
                        .font(.caption.weight(.semibold))
                        .lineLimit(1)
                    if item.address != "" {
                        Text(item.address)
                            .font(.footnote)
                            .foregroundColor(.secondary)
                        Text(item.city + ", " + item.state)
                            .font(.footnote)
                            .foregroundColor(.secondary)
                    } else {
                        Text("N/A")
                    }
                }
                .frame(width: geo.size.width * 0.3)

                Divider()

                // 右侧占70%宽度
                VStack(alignment: .leading, spacing: 3) {
                    HStack(spacing: 3) {
                        VStack(alignment: .leading) {
                            Text("Weather")
                                .font(.caption.weight(.semibold))
                                .lineLimit(1)
                            HStack(alignment: .firstTextBaseline, spacing: 3) {
                                Image(systemName: "waveform")
                                    .imageScale(.small)
                                    .foregroundColor(.secondary)
                                Text("79%")
                                    .font(.caption.weight(.regular))
                                    .foregroundColor(.secondary)
                            }
                        }
                        .frame(width: (geo.size.width * 0.7 - 3) * 0.5)

                        Divider()

                        Text("Hello, World!")
                            .frame(width: (geo.size.width * 0.7 - 3) * 0.5, alignment: .leading)
                    }

                    Divider()

                    HStack(spacing: 3) {
                        Text("Hello, World!")
                            .frame(width: (geo.size.width * 0.7 - 3) * 0.5, alignment: .leading)
                        Divider()
                        Text("Hello, World!")
                            .frame(width: (geo.size.width * 0.7 - 3) * 0.5, alignment: .leading)
                    }
                }
                .frame(width: geo.size.width * 0.7)
            }
        }
    }
}

方案对比

  • Grid:原生支持,代码结构清晰,自动适配不同屏幕,是iOS16+版本的最优选择。
  • GeometryReader:兼容性强,能覆盖旧系统,但需要手动计算宽度,代码相对繁琐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:30:39