Why gesture start working outside of frame in SwiftUI?

Viewed 175

I have a Rec that I can move it in gesture action, but the problem is that gesture start capturing gesture in outside of its frame, which I expect just working inside the frame. here is the code and gif about issue:

gif:

enter image description here

code:

    struct ContentView: View {
    
    @State private var recLocation: CGFloat = CGFloat()
    @GestureState private var recTranslation: CGFloat = CGFloat()
    
    var body: some View {
        
        GeometryReader { geometry in
            
            Rectangle().fill(Color.red).frame(width: 50, height: 50, alignment: .center)
                .position(x: recLocation + recTranslation + 25, y: geometry.size.height/2)
                .gesture( DragGesture()
                            .updating($recTranslation) { value, state, translation in
                                state = value.translation.width
                            }
                            .onEnded { value in
                                recLocation = recLocation + value.translation.width
                            } )
            
            
        }
        
    }
}
1 Answers

From what I know every time I use GeometryReader the sizes of my container gets messed up, I tried to find a solution since the first minute you have posted this question because it's very interesting and here it is how to overcome this problem:

GeometryReader { geometry in
    
    Rectangle()
        .fill(Color.red)
        .frame(width: 50, height: 50)
        .position(x: recLocation + recTranslation + 25, y: geometry.size.height/2)
        .overlay(
            Rectangle()
                .fill(Color.blue)
                .frame(width: 23.5, height: 23.5)
                .position(x: recLocation + recTranslation + 25, y: geometry.size.height/2)
                .opacity(0.001)
                .gesture( DragGesture()
                            .updating($recTranslation) { value, state, translation in
                                state = value.translation.width
                            }
                            .onEnded { value in
                                recLocation = recLocation + value.translation.width
                            } )
        )
    
}.frame(width: 50, height: 50)
}

Explanation:

Basically what I saw is that the DragGesture is detected outside the boundary of your Rectangle, by that I have created an Overlay with the same shape and with less size, and make the DragGesture to the Overlay.

Note: Don't forget to put the Overlay shape Opacity to 0.001, by that it will be invisible but still interactive.

Voila! everything seems perfect.

Result

Related