首页 > 解决方案 > Swift UI 将 VStack 子项高度调整为内容高度

问题描述

我有一个带三个孩子的 VStack。这些孩子中的每一个都有一个 HStack,左边有一些文本和一个空白区域。这是预览的屏幕截图,其中 VStack 子项周围带有突出显示的边框,每个 HStack 周围都有突出显示的边框。

虚拟堆栈视图 HStack 视图

如何将每个 VStack 子项设置为缩小到 HStack 的高度并摆脱底部的空白空间?现在这个问题似乎是由默认情况下 VStack 填充整个屏幕并将每个孩子设置为相等的高度引起的。

当前代码:

import Foundation
import SwiftUI


struct NameAndConnection: View {
    var body: some View {
        VStack(alignment: .leading) {
            Text(data.name)
               .font(.headline)
               .fontWeight(.semibold)
               .foregroundColor(Color.black)
               .frame(alignment: .leading)
   
            Text(data.connection)
               .font(.callout)
               .fontWeight(.medium)
               .foregroundColor(Color.gray)
               .frame(alignment: .leading)
        }
    }
}

struct Description: View {
    var body: some View {
        Text(data.description)
    }
}

struct Post: View {
    var body: some View {
        GeometryReader { geo in
            HStack(alignment: .top, spacing: 0) {
                Spacer()
                VStack(alignment: .leading) {
                    NameAndConnection()
                    Description()
                        .padding(.top, 1.0)
                }
                .frame(width: geo.size.width * 0.75)
            }
        }
    }
}



struct PostView: View {
    var body: some View {
        GeometryReader { geo in
            VStack() {
                Post()
                Post()
                Post()
            }
        }
    }
}

标签: swiftlayoutswiftuivstackhstack

解决方案


GeometryReader将占用所有可用空间。一般来说,尝试GeometryReader谨慎使用并针对不同的屏幕尺寸提出其他更灵活的解决方案被广泛认为是一种好的做法。

当您必须使用它时,通常测量 a 的背景会很有帮助View- 这样,它View本身就不会像GeometryReader在前景中那样增长。我借用了GeometryReaderhttps ://stackoverflow.com/a/59733037/560942

删除GeometryReaders 后,您可以使用 aSpacer将其他VStacks 推到屏幕顶部。

struct GeometryGetter: View {
    @Binding var rect: CGRect

    var body: some View {
        GeometryReader { (g) -> Path in
            print("width: \(g.size.width), height: \(g.size.height)")
            DispatchQueue.main.async {
                self.rect = g.frame(in: .global)
            }
            return Path() // could be some other dummy view
        }
    }
}

struct Post: View {
    @State private var rect1: CGRect = CGRect()
    
    var body: some View {
        HStack(alignment: .top, spacing: 0) {
            Spacer()
            VStack(alignment: .leading) {
                NameAndConnection()
                Description()
                    .padding(.top, 1.0)
            }.frame(width: rect1.width * 0.75)
        }
        .background(GeometryGetter(rect: $rect1))
        .border(Color.green)
    }
}



struct ContentView: View {
    var body: some View {
            VStack() {
                Post()
                Post()
                Post()
                Spacer()
            }
    }
}

推荐阅读