为什么 ZStack 不能在 SwiftUI 中使用设备高度?

How come ZStack is not working with device height in SwiftUI?

所以我在做一个项目,每当我制作一个 ZStack 来获得背景颜色时,后续的 VStack 基本上都会以某种方式附加到 ZStack。我认为 ZStack 类似于相互堆叠的对象。

但是,我使 bottomHeightMultiplier var 越接近 100%,Vstack 中的文本就越多地被推出屏幕。我只是想创建一个背景视图,其中任何设备屏幕的顶部 20% 为白色,屏幕底部 80% 为绿色。

不幸的是,Text("Enter bill total") 最终被推出了屏幕。如果我将 Spacer() 放在文本下方,它会被推到顶部并超出安全区域。将它放在文本上方会将其推到底部并超出安全区域。



import SwiftUI

struct CalculatorScreen: View {
    
    var screenWidth = UIScreen.main.bounds.width
    var screenHeight = UIScreen.main.bounds.height
    var topHeightMultiplier: CGFloat = 0.20
    var bottomHeightMultiplier: CGFloat = 0.80

    
    var body: some View {
        
        ZStack {
 

            VStack {
                Color.white
                    .frame(minHeight: screenHeight*topHeightMultiplier)
                
                Color.green
                    .frame(minHeight: screenHeight*bottomHeightMultiplier)
            }


            VStack {
                Spacer()
                Text("Enter bill total")
                    .foregroundColor(.black)

            }   
            
        }
        
    }
}



这样就可以了。真正发生的是,当使用 UIScreen.bounds 时,安全区域会产生问题,使视图比屏幕长。这意味着内部 VStack 推动外部 ZStack,从而使 ZStack 也比设备更长。因此,ZStack 中的对象不是完全独立的,但是当子对象的大小发生变化时,父对象的大小也会发生变化,从而隐式地影响 ZStack 中的其他子对象。由于 Spacer(),第二个 VStack 将与 ZStack 一样长,使其看起来像是被推离了屏幕。

此外,颜色的 VStack 有一个标准的填充(现在添加了 spacing: 0),在颜色之间创建了一条白线,同时消耗了 space,当计算颜色的高度。我的建议是在构建块时始终使用您可以看到的颜色,这样您可以立即发现安全区域问题和不需要的填充。

struct CalculatorScreen: View {
    
    var topHeightMultiplier: CGFloat = 0.20
    var bottomHeightMultiplier: CGFloat = 0.80

    var body: some View {
        GeometryReader { geometry in
            ZStack {
                VStack(spacing: 0) {
                    Color.purple
                        .frame(minHeight: geometry.size.height*topHeightMultiplier)
                    Color.green
                        .frame(minHeight: geometry.size.height*bottomHeightMultiplier)
                }
                .ignoresSafeArea()

                VStack {
                    Spacer()
                    Text("Enter bill total")
                        .foregroundColor(.black)

                }
            }
        }
    }
}