1

When I created three Button()s View and I want GeometryReader to access individual Button()'s location in the frame. Although in the UI the Button()s show their location according to .position() modifier, the GeometryReader, however, print out the same Y location for all three Button()s:

Button 3
minX: 125.83333333333334, maxX: 183.5
minY: 31.0, maxY: 193.0

Button 2
minX: 63.166666666666664, maxX: 120.83333333333334
minY: 31.0, maxY: 193.0

Button 1
minX: 0.5, maxX: 58.166666666666664
minY: 31.0, maxY: 193.0

The code is:

struct Learn_W_SingleButton: View {
    

    let buttonID: Int
    
    func buttonAction() {
        print("pressed \(buttonID)")
    }
    
    var body: some View {
        Button(action: buttonAction){
            Circle()
                .fill(Color.white)
                .frame(width: 50, height: 50)
                .shadow(radius: 10)
                .overlay(
                    Image(systemName: "heart.fill")
                        .foregroundColor(Color.red)
                        .font(.title2)
                )
        }
        .buttonStyle(.borderless)
            
    }
}


struct Learn_W_ThreeButtonsView_Ask: View {
    
    
    let button1 = Learn_W_SingleButton(buttonID: 0)
    let button2 = Learn_W_SingleButton(buttonID: 1)
    let button3 = Learn_W_SingleButton(buttonID: 2)
    
    
    var body: some View {
        

        GeometryReader { geo in
            HStack {
                GeometryReader { geo1 in
                    button1
                        .position(x: 50, y: 50)
                        .onAppear( perform: {
                            print()
                            print("Button 1")
                            print("minX: \(geo1.frame(in: .global).minX), maxX: \(geo1.frame(in: .global).maxX)")
                            print("minY: \(geo1.frame(in: .global).minY), maxY: \(geo1.frame(in: .global).maxY)")
                            
                        })
                }
                GeometryReader { geo2 in
                    button2
                        .position(x: 50 , y: 20
                        )
                        .onAppear( perform: {
                            print()
                            print("Button 2")
                            print("minX: \(geo2.frame(in: .global).minX), maxX: \(geo2.frame(in: .global).maxX)")
                            print("minY: \(geo2.frame(in: .global).minY), maxY: \(geo2.frame(in: .global).maxY)")
                        })
                }
                GeometryReader { geo3 in
                    button3
                        .position(x: 50, y: 100)
                        .onAppear(perform: {
                            print()
                            print("Button 3")
                            print("minX: \(geo3.frame(in: .global).minX), maxX: \(geo3.frame(in: .global).maxX)")
                            print("minY: \(geo3.frame(in: .global).minY), maxY: \(geo3.frame(in: .global).maxY)")
                        })
                }
                
                
            }
            
        }
        
        
    }
}


struct Learn_W_dragGesture_Previews: PreviewProvider {
    static var previews: some View {
        Learn_W_ThreeButtonsView_Ask()
    }
}

It'd be great if you could help how to print out the correct location of each components in such View() Thank you.

Jason
  • 3,166
  • 3
  • 20
  • 37

1 Answers1

0

GeometryReader does not read location of internal element, it reads available outer space in a place where it is created.

If you want to read frame of specific view you can use GeometryReader placed into background of that view, because background has same size, so GeometryReader getting all background space can provide its coordinates in specified space.

Here is one variant of usage https://stackoverflow.com/a/60214735/12299030, direct but in two steps.

Here is demo of another based on view preference https://stackoverflow.com/a/71613003/12299030

Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Would it be possible for you to edit on top of the code snippet here? I read the links, but don't think it really provides insights on this issue – Jason Jun 02 '22 at 22:26