Here is a very simple example to show what I try to do. The red circle can be dragged around and when it is released it will go back to the original place, as shown in the first image. The problem occurs when iPad dock is pulled up in the middle of dragging and then the DragGesture's .onEnded
will never be called and the red circle is stuck, as shown in the second image. I don't understand why .onEnded
isn't called. What am I missing here?
I thought of a workaround by resetting offset
in SceneDelegate's sceneDidBecomeActive
, but it doesn't work if iPad dock is just pulled up but doesn't cause the app to become inactive, i.e. going to background mode. In this case, no functions in SceneDelegate will be called and I find it impossible to detect that DragGesture has been interrupted. Any possible solution?
struct ContentView: View {
@State private var offset = CGSize.zero
var body: some View {
ZStack {
Rectangle()
.fill(Color.clear)
.frame(width: 100, height: 100)
.border(Color.black, width: 5)
Circle()
.fill(Color.red)
.frame(width: 90, height: 90)
.offset(offset)
.gesture(
DragGesture()
.onChanged() { self.offset = $0.translation }
.onEnded() { _ in self.offset = CGSize.zero })
}
}
}
Try with GestureState
as follows. It is temporary, by default, and when ended is reset to initial value by design.
struct ContentView: View {
@GestureState private var offset = CGSize.zero
var body: some View {
ZStack {
Rectangle()
.fill(Color.clear)
.frame(width: 100, height: 100)
.border(Color.black, width: 5)
Circle()
.fill(Color.red)
.frame(width: 90, height: 90)
.offset(offset)
.gesture(
DragGesture()
.updating($offset) { (value, gestureState, transaction) in
gestureState = CGSize(width: value.location.x - value.startLocation.x, height: value.location.y - value.startLocation.y)
})
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With