SwiftUI:根据顶层在ZStack中安排中间层

SwiftUI: Arrange middle layer in ZStack dependent on top layer

我想实现一个UI,其中有

  1. 背景图片,全屏并随设备尺寸缩放
  2. 在背景图像上方和主图像下方的渐变 UI,底部对齐,其大小取决于主图像中一个元素的位置 UI
  3. 主要 UI 具有多个界面元素的 VStack。有一个顶部区域和一个底部区域,它们都是固定对齐和大小的,中间有一个可变的间隔

此模型显示了 3 层 ZStack 的预期排列(从左到右):

这是我在 Swift 中得到的UI:

struct TestView: View {
    
    var body: some View {
        ZStack() {
            // BG Image
            Image("BgImg")
                .resizable()
                .scaledToFill()
                .frame(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.width)
            
            // Gradient
            VStack {
                Spacer()
                Rectangle()
                    .fill(
                        LinearGradient(gradient: Gradient(stops: [
                            Gradient.Stop(color: Color(.black).opacity(0.0), location: 0),
                            Gradient.Stop(color: Color(.black), location: 0.5),
                        ]), startPoint: .top, endPoint: .bottom)
                    )
                    // HOW TO GET THE RIGHT SIZE HERE?
                    .frame(height:500)
            }
            
            // Main UI
            VStack {
                // VStack 1
                VStack {
                    Text("ABC")
                    Text("DEF")
                }.frame(height:260)
                
                // Fixed spacer
                Spacer().frame(height:26)
                
                // VStack 2
                VStack {
                    Text("123").foregroundColor(.white)
                    Text("456").foregroundColor(.white)
                }.frame(height:162)
                
                // Variable spacer
                Spacer()
                
                // VStack 2
                VStack {
                    Text("!!!").foregroundColor(.white)
                    Text("???").foregroundColor(.white)
                }.frame(height:304)
            }
            // Fixed spacer top
            .padding(.top, 26)
            // Fixed spacer bottom
            .padding(.bottom, 32)
            
        }
        .edgesIgnoringSafeArea(.all)
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
            .previewDevice("iPhone 13 Pro")
            .preferredColorScheme(.light)
    }
}

我的问题是:

  1. 如何正确调整渐变大小?
  2. 为什么渐变现在对齐到底部,为什么背景图像不能缩放到全屏,请参见预览屏幕截图的底部

对于非全屏的图片,需要让图片忽略安全区域,而不仅仅是ZStack;

您需要使用几何体 reader 读取直到堆栈末尾的高度,然后将其分配给用于调整渐变大小的值。