首页 > 解决方案 > SwiftUI 在 ZStack 中不居中

问题描述

我正在尝试组合一个视图,该视图由顶部标题视图、底部内容视图和位于顶部的视图组成,该视图以分割两个视图的线为中心。我发现我需要一个 ZStack 中的对齐指南来定位中间视图,但是我无法让下部内容视图中的项目居中而没有间隙。

这段代码:

extension VerticalAlignment {
    struct ButtonMid: AlignmentID {
        static func defaultValue(in context: ViewDimensions) -> CGFloat {
            return context[.bottom]
        }
    }
    static let buttonMid = VerticalAlignment(ButtonMid.self)
}

struct ContentView: View {
    var body: some View {
        VStack {
            ZStack(alignment: Alignment(horizontal: .center, vertical: .buttonMid)) {
                HeaderView()
                    .frame(maxWidth: .infinity, minHeight: 200, idealHeight: 200, maxHeight: 200, alignment: .topLeading)
                
//                BodyView()
//                    .alignmentGuide(.buttonMid, computeValue: { dimension in
//                        return dimension[VerticalAlignment.top]
//                    })
                
                Color.red
                    .frame(width: 380, height: 50, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
                    .alignmentGuide(.buttonMid, computeValue: { dimension in
                        return dimension[VerticalAlignment.center]
                    })
            }
            
            BodyView()
        }
        .edgesIgnoringSafeArea(.top)
    }
}

struct HeaderView: View {
    var body: some View {
        Color.green
    }
}

struct BodyView: View {
    var body: some View {
        VStack {
            Spacer()
            HStack {
                Spacer()
                BodyContent()
                Spacer()
            }
            Spacer()
        }
        .background(Color.blue)
    }
}

struct BodyContent: View {
    var body: some View {
        VStack {
            Text("Line 1")
            Text("Line 2")
            Text("Line 3")
        }
    }
}

给你这个:

在此处输入图像描述

它以我想要的方式将较低的内容居中,但是它在上下视图之间留下了间隙。如果我取消注释 ZStack 中的 BodyView 代码并在 VStack 中将其注释掉,如下所示:

struct ContentView: View {
    var body: some View {
        VStack {
            ZStack(alignment: Alignment(horizontal: .center, vertical: .buttonMid)) {
                HeaderView()
                    .frame(maxWidth: .infinity, minHeight: 200, idealHeight: 200, maxHeight: 200, alignment: .topLeading)
                
                BodyView()
                    .alignmentGuide(.buttonMid, computeValue: { dimension in
                        return dimension[VerticalAlignment.top]
                    })
                
                Color.red
                    .frame(width: 380, height: 50, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
                    .alignmentGuide(.buttonMid, computeValue: { dimension in
                        return dimension[VerticalAlignment.center]
                    })
            }
            
//            BodyView()
        }
        .edgesIgnoringSafeArea(.top)
    }
}

给你:

在此处输入图像描述

这使内容不居中。我怎样才能让它居中?我试着把它放在一个 GeometryReader 中,结果是一样的。

标签: swiftui

解决方案


您不需要自定义VerticalAlignment. 相反,您可以将中间视图作为叠加层并将其与底部视图的顶部边框对齐:

struct ContentView: View {
    var body: some View {
        VStack(spacing: 0) {
            HeaderView()
                .frame(height: 200)
            BodyView()
                .overlay(
                    Color.red
                        .frame(width: 380, height: 50)
                        .alignmentGuide(.top) { $0[VerticalAlignment.center] },
                    alignment: .top
                )
        }
        .edgesIgnoringSafeArea(.top)
    }
}

推荐阅读