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

SwiftUI中使用Stack实现网格布局的优化问题

SwiftUI Stack网格布局优化方案

优化后的完整代码

import SwiftUI

// 用于传递视图高度的PreferenceKey
struct ViewHeightKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}

struct ForStackOverflow: View {
    let spacerSize: CGFloat = 1
    @State private var leftContainerHeight: CGFloat = 0

    var body: some View {
        GeometryReader { geometry in
            let totalWidth = geometry.size.width
            // 计算与A/D一致的单组件宽度
            let componentWidth = (totalWidth - 3 * spacerSize) / 4
            
            VStack(spacing: spacerSize) {
                HStack(spacing: spacerSize) {
                    makeComponent(text: "A")
                    makeComponent(text: "B")
                    makeComponent(text: "C")
                    makeComponent(text: "D")
                }
                
                HStack(spacing: spacerSize) {
                    VStack(spacing: spacerSize) {
                        HStack(spacing: spacerSize) {
                            makeComponent(text: "E")
                            makeComponent(text: "F")
                            makeComponent(text: "G")
                        }
                        HStack(spacing: spacerSize) {
                            makeComponent(text: "H")
                            makeComponent(text: "I")
                            makeComponent(text: "J")
                        }
                        HStack(spacing: spacerSize) {
                            makeComponent(text: "K")
                        }
                    }
                    // 捕获左侧容器的实际高度
                    .background(
                        GeometryReader { proxy in
                            Color.clear
                                .preference(key: ViewHeightKey.self, value: proxy.size.height)
                        }
                    )
                    
                    makeComponent(text: "L")
                        .frame(width: componentWidth)
                        .frame(height: leftContainerHeight)
                }
            }
        }
        .onPreferenceChange(ViewHeightKey.self) { newHeight in
            leftContainerHeight = newHeight
        }
    }
    
    func makeComponent(text: String) -> some View {
        Text(text)
            .frame(minWidth: 0, maxWidth: .infinity)
            .frame(height: 80)
            .background(Color.red)
            .foregroundColor(.white)
    }
}

struct ForStackOverflow_Previews: PreviewProvider {
    static var previews: some View {
        ForStackOverflow()
    }
}

问题1:L宽度与D一致的优化

  • 替换硬编码的UIScreen.main.bounds.width,改用GeometryReader获取当前视图的实际可用宽度,适配分屏、安全区等复杂场景。
  • 通过公式(总宽度 - 3*间距)/4计算出和A/D完全一致的单组件宽度,直接应用到L的宽度设置中,保证布局匹配。

问题2:L高度匹配G+J+K总和的优化

  • 采用PreferenceKey机制自动捕获左侧容器(包含G、J、K的VStack)的实际高度,无需手动计算80*3 + 2*间距这类固定值。
  • 实现逻辑:
    1. 定义ViewHeightKey继承PreferenceKey,用于传递高度数据。
    2. 在左侧VStack的背景中嵌入GeometryReader,获取容器高度并通过preference传递。
    3. 用onPreferenceChange接收高度值,同步设置L的高度,实现自动匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 22:46:02