Search code examples
swiftswiftuialignmentios16

SWIFTUI: .overlay breaks alignment


I have this bit of code below where I'm trying to have a rectangle centered in the screen, where I overlay a text outupt from some function and a share button. The concept works, except that when I add the .overlay, the "text box" (the rectangle with the text and share button overlayed to it) lose the centered alignment and they move to the left.If I remove the .overlay, the rectangle is centered but the content remains behind it. What am I doing wrong? Thanks.

GeometryReader { geometry in  // Debug alignment
    VStack(alignment: .center) {  //TextBox

        Rectangle()
         .fill(Color.cyan)
         .cornerRadius(20)
         .frame(width: geometry.size.width * 0.75, height: 200, alignment: .center)
         .overlay(
            ScrollView {
                HStack(alignment: .top){
                    VStack(alignment: .center) {
                        
                        Text(responseText)
                            .foregroundColor(.black)
                            .frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
                            .layoutPriority(2)
                    }
                    
                    ShareLink(item: responseText){
                        Image(systemName: "square.and.arrow.up")
                        
                            .resizable()
                            .scaledToFit()
                            .frame(width: 25, height: 25)
                        
                    }
                    
                    
                }
            }
    )
                
    } //Vstack Top
}  //Geo Reader    

I tried to center the recantgle while using the .overlay to put the conetent on top of it but the centered aligment gets lost. I also tried to use a ZStack instead of a .overlay but the content remains hidden behind.


Solution

  • GeometryReader positions its children at its top left. The VStack child of GeometryReader hugs its children—in this case, its single child, which is a Rectangle with a fixed frame.

    Put the Rectangle in a container that expands to the size of the enclosing GeometryReader and centers the Rectangle within the expanded size.

    For example, add a frame(maxWidth: .infinity, maxHeight: .infinity) modifier on the VStack:

    GeometryReader { geometry in  // Debug alignment
        VStack {
            Rectangle()
                .fill(Color.cyan)
                etc. etc.
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
    

    Result:

    iPhone screen shot showing a blue rounded rectangle in the middle of the screen with text and a share button overlaid on it.

    But if you don't have anything else to put in the VStack, you can remove it and put the frame modifier directly on the Rectangle, after the overlay:

    GeometryReader { geometry in  // Debug alignment
        Rectangle()
            .fill(Color.cyan)
            .cornerRadius(20)
            .frame(width: geometry.size.width * 0.75, height: 200)
            .overlay(
                ScrollView {
                    HStack(alignment: .top){
                        Text(responseText)
                            .foregroundColor(.black)
    
                        ShareLink(item: responseText) {
                            Image(systemName: "square.and.arrow.up")
                                 .resizable()
                                .scaledToFit()
                                .frame(width: 25, height: 25)
                        }
                    }
                }
            )
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }