How to Vertically Centre a view in relation to the top border

How to Vertically Centre a view in relation to the top border

I would like to vertically centre a view in relation to the top border using SwiftUI. In UIKit this is really easy with layout anchors however I am really struggling to work out how to do this in SwiftUI. I have tried to achieve this using an overlay and GeometryReader but that hasn't worked.

So in the image below I want the call out text's vertical centre to be in line with the top border. I do not wish to manually add a negative y offset as the text is dynamic unless using a Geometry Reader.

enter image description here

This is the code I have

import SwiftUI

struct ContentView: View {
    var body: some View {
        Button {
        
        } label: {
            VStack(alignment: .leading, spacing: 6) {
                Text("Some Information")
                    .font(.headline)
                Text("Other")
                    .font(.footnote)
            }
            .padding()
            .padding(.top, 8)
        }
        .overlay {
            RoundedRectangle(cornerRadius: 12)
                .stroke(Color(uiColor: .systemGreen), lineWidth: 4)
        }
        .overlay(alignment: .topTrailing) {
            Text("CALL OUT")
                .font(.footnote)
                .foregroundStyle(.white)
                .padding(.vertical, 6)
                .padding(.horizontal, 12)
                .background {
                    RoundedRectangle(cornerRadius: 12)
                        .fill(Color(uiColor: .systemGreen))
                }
        }
    }
}

#Preview {
    ContentView()
}

Answer

You just need to apply an .alignmentGuide to the overlay:

.overlay(alignment: .topTrailing) {
    Text("CALL OUT")
        .font(.footnote)
        .foregroundStyle(.white)
        .padding(.vertical, 6)
        .padding(.horizontal, 12)
        .background {
            RoundedRectangle(cornerRadius: 12)
                .fill(Color(uiColor: .systemGreen))
        }
        .alignmentGuide(.top) { dim in // 👈 here
            dim[VerticalAlignment.center]
        }
}

Screenshot

If you want to move it in a bit from the trailing edge, just add some trailing padding after the .background modifier. Alternatively, you could add another alignment guide for the horizontal alignment, this time it would be .alignmentGuide(.trailing). But adding padding is perhaps simpler.

Enjoyed this article?

Check out more content on our blog or follow us on social media.

Browse more articles