Gerrit
Gerrit

Reputation: 2677

How to align a VStack with 80% width with Texts centrally when it is in a ZStack?

I want to place a VStack including a few Text-Views in the center of the screen with a white background and opacity 50%. Therefore I tried the GeometryReader and know that it tries to consume 100% of the available size, but the end result looks strange. When I try to inspect the elements it seems to be caused by the ZStack containing the background image.

What do I need to do to align the VStack in the center?

ZStack {
            Image("demo-bg")
                .resizable()
                .scaledToFill()
                .edgesIgnoringSafeArea(.all)
            GeometryReader { proxy in
                VStack {

                    Text("Test1")
                        .font(.largeTitle)
                        .foregroundStyle(.green)
                    Text("Test2")
                        .font(.largeTitle)
                        .foregroundStyle(.red)
                    Text("Test3")
                        .font(.largeTitle)
                        .foregroundStyle(.green)
                    Text("Test4")
                        .font(.largeTitle)
                    TextField("Result", text: $result).keyboardType(.numberPad)
                }
                .frame(width: proxy.size.width * 0.8)
                .background(.white)
            }
        }

/Preview in XCode

Upvotes: 0

Views: 36

Answers (1)

Benzy Neez
Benzy Neez

Reputation: 20759

I would suggest showing the Image using a .background modifier, so that the size of the image doesn't affect the layout. Then:

  • The ZStack is not needed any more, you can apply the image as background to the GeometryReader instead.
  • As you mentioned, a GeometryReader grabs all the available space. Unlike HStack, VStack and ZStack, which use center-alignment by default, the content of a GeometryReader is positioned with top-leading alignment. So after you have sized the main content to the size you want it to have and applied a background color (white), increase its size using maxWidth: .infinity, maxHeight: .infinity. This way, it fills the space of the GeometryReader.
  • The .frame modifier uses center alignment by default. If in fact you want some other kind of alignment, add an alignment parameter too.
  • Also, .edgesIgnoringSafeArea is deprecated, suggest using .ignoresSafeArea instead.
var body: some View {
    GeometryReader { proxy in
        VStack {
            // ...
        }
        .frame(width: proxy.size.width * 0.8)
        .background(.white)
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
    .background {
        Image("demo-bg")
            .resizable()
            .scaledToFill()
            .ignoresSafeArea()
    }
}

Screenshot

Upvotes: 1

Related Questions