SwiftUI如何在VStack内部垂直居中放置视图

时间:2020-10-08 16:08:21

标签: swiftui vertical-alignment vstack

我想在屏幕的垂直中心有一个视图,在屏幕的顶部有一个视图,在这两个视图之间垂直居中有一个视图,就像这样:

enter image description here

这花了我5分钟时间在情节提要上做,但是我似乎找不到在SwiftUI?中做这件事的方法。

我已经尝试了多个zstack,vstack,多个自定义对齐方式,但这是我得到的最接近的结果:

struct SelectionView: View {
    var body: some View {
        ZStack(alignment: .myAlignment) {
            Color.green
                .edgesIgnoringSafeArea(.all)
            
            
            VStack {
                Image(systemName: "clock")
                    .resizable()
                    .foregroundColor(.white)
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 156, height: 80)
                
//                Spacer()
                
                Text("My\nmultiline label")
                    .multilineTextAlignment(.center)
                    .font(.title)
                    .foregroundColor(.white)

//                Spacer()
                
                VStack(spacing: 16) {
                    RoundedRectangle(cornerRadius: 5).fill(Color.white).frame(height: 79)
                    RoundedRectangle(cornerRadius: 5).fill(Color.white).frame(height: 79)
                }
                .alignmentGuide(VerticalAlignment.myAlignment) { dimension in
                    dimension[VerticalAlignment.center]
                }
                .layoutPriority(1)
            }
            .padding([.leading, .trailing], 24)
        }
    }
    
}

struct SelectionView_Previews: PreviewProvider {
    static var previews: some View {
        LanguageSelectionView()
    }
}

// MARK

extension HorizontalAlignment {
  
    enum MyHorizontal: AlignmentID {
        static func defaultValue(in d: ViewDimensions) -> CGFloat
                 { d[HorizontalAlignment.center] }
    }

    static let myAlignment =
                 HorizontalAlignment(MyHorizontal.self)
}

extension VerticalAlignment {
    enum MyVertical: AlignmentID {
        static func defaultValue(in d: ViewDimensions) -> CGFloat
                 { d[VerticalAlignment.center] }
    }
  
    static let myAlignment = VerticalAlignment(MyVertical.self)
}

extension Alignment {
    static let myAlignment = Alignment(horizontal: .myAlignment,
                               vertical: .myAlignment)
}

我将GeometryReader保留为最后的手段,因为对于这种看似简单的布局来说,这似乎太过严格了。

我想我正在以某种错误的方式来处理这个问题(我的头上仍然有太多UIKit /约束)。

1 个答案:

答案 0 :(得分:1)

这是可能的解决方案。经过Xcode 12 / iOS 14的测试

demo

struct SelectionView: View {
    var body: some View {
        ZStack {
            Color.green
                .edgesIgnoringSafeArea(.all)
            
            VStack(spacing: 16) {
                Color.clear
                    .overlay(
                        VStack {
                            Image(systemName: "clock")
                                .resizable()
                                .foregroundColor(.white)
                                .aspectRatio(contentMode: .fit)
                                .frame(width: 156, height: 80)
                            Color.clear
                                .overlay(
                                    Text("My\nmultiline label")
                                        .multilineTextAlignment(.center)
                                        .font(.title)
                                        .foregroundColor(.white)
                            )
                        }
                    )
                RoundedRectangle(cornerRadius: 5).fill(Color.white).frame(height: 79)
                RoundedRectangle(cornerRadius: 5).fill(Color.white).frame(height: 79)
                Color.clear
            }
            .padding([.leading, .trailing], 24)
        }
    }
}
相关问题