Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why gesture start working outside of frame in SwiftUI?

Tags:

swiftui

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
                            } )
            
            
        }
        
    }
}
like image 646
ios coder Avatar asked Dec 16 '20 14:12

ios coder


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

like image 175
Cod3rMax Avatar answered Dec 23 '22 16:12

Cod3rMax