So I have this really nice animation I want when a user presses a view, where it will sort of "bounce" under their finger as if it reacted to the touch.
Initial Goal
I need to register when the user presses down on the view (black rectangle in this example), so I can start shrinking it, then I need to register when they release on the view, so I can allow it to return to it's original size. User needs to still be able to scroll normally in ScrollView
Initial "Solution"
I managed to achieve the desired animation using DragGesture() gesture with minimumDistance: 0.
This is achieved with the following code:
@State private var pressed: Bool = false
var body: some View {
let drag = DragGesture(minimumDistance: 0)
.onChanged({_ in
self.pressed = true
})
.onEnded({_ in
self.pressed = false
})
return ScrollView {
Rectangle()
.frame(minHeight: 100)
.scaleEffect(self.pressed ? 0.5 : 1)
.animation(.easeInOut)
// .onTapGesture(perform: {
// self.pressed.toggle()
// })
.gesture(drag)
}
}
Problem
If you user begins to scroll by starting with their finger on the rectangle, it will register as a drag gesture. If they begin scrolling elsewhere, scrolling is as normal
Alternative
If I use the modifier .onTapGesture() then I can tap and it's registered, and also begin scrolling and it registers as a scroll as appropriate
This is achieved with the following code:
@State private var pressed: Bool = false
var body: some View {
let drag = DragGesture(minimumDistance: 0)
.onChanged({_ in
self.pressed = true
})
.onEnded({_ in
self.pressed = false
})
return ScrollView {
Rectangle()
.frame(minHeight: 100)
.scaleEffect(self.pressed ? 0.5 : 1)
.animation(.easeInOut)
.onTapGesture(perform: {
self.pressed.toggle()
})
// .gesture(drag)
}
}
Question
So how can I still get the desired animation whilst allowing scrolling? I've looked into GestureMasks, simultaneousGesture, LongPressGesture and more and they don't achieve the quick responsive animation I'm looking for...
Thanks!