Home > other >  How to align the middle of a View to the bottom of other view in SwiftUI?
How to align the middle of a View to the bottom of other view in SwiftUI?

Time:01-04

So basically I need to come up with a layout that aligns the middle of a View to the bottom of other View in SwiftUI. To make it more clear, all I need is something like this:

enter image description here

I guess the equivalent in a UIKit world would be:

redView.bottomAnchor.constraint(equalTo: whiteView.centerYAnchor)

Ive tried setting both in a ZStack and offsetting the white View but it won't work on all screen sizes for obvious reasons.

Any tips?

CodePudding user response:

You can use .aligmentGuide (which is a tricky beast, I recommend this explanation)

Here is your solution, its independent of the child view sizes:

struct ContentView: View {
    
    var body: some View {
        
        ZStack(alignment: .bottom) { // subviews generally aligned at bottom
            redView
            whiteView
                // center of this subview aligned to .bottom
                .alignmentGuide(VerticalAlignment.bottom, 
                                computeValue: { d in d[VerticalAlignment.center] }) 
        }
        .padding()
    }
    
    var redView: some View {
        VStack {
            Text("Red View")
        }
        .frame(maxWidth: .infinity)
        .frame(height: 200)
        .background(Color.red)
        .cornerRadius(20)
    }
    
    var whiteView: some View {
        VStack {
            Text("White View")
        }
        .frame(maxWidth: .infinity)
        .frame(width: 250, height: 100)
        .background(Color.white)
        .cornerRadius(20)
        .overlay(RoundedRectangle(cornerRadius: 20).stroke())
    }
    
}

CodePudding user response:

You may try this:

        ZStack {
        Rectangle()
            .frame(width: 300, height: 400)
            .overlay(
                GeometryReader { proxy in
                    
                    let offsetY = proxy.frame(in: .named("back")).midY
                    Rectangle()
                        .fill(Color.red)
                        .offset(y: offsetY)
                }
                    .frame(width: 150, height: 140)
                , alignment: .center)
    }
    .coordinateSpace(name: "back")

Bascially the idea is to use coordinateSpace to get the frame of the bottom Rectangle and use geometryreader to get the offset needed by comparing the frame of top rectangle with the bottom one. Since we are using overlay and it is already aligned to the center horizontally, we just need to offset y to get the effect you want.

  • Related