I'm currently developing an application using SwiftUI
and trying to make a swipe component.
When I use DragGesture
and onTapGesture
together, that swipe motion does not move smoothly...
If I make onTapGesture
disable the swipe motion work well.
But I want to use both of them together.
How could I solve this problem?
Here is the code:
import SwiftUI
struct SwipeTest1: View {
@State var offset : CGFloat = 0
@State var isOn = false
@State var isOnTap = false
var body: some View {
VStack{
Text(isOnTap ? "isOnTap: ON" : "isOnTap: OFF")
ZStack{
Capsule()
.fill(Color.primary.opacity(0.1))
VStack{
Spacer()
Circle()
.fill(isOn ? Color.blue : Color.green )
.frame(width: 60, height: 60)
.offset(y:offset)
.onTapGesture {isOnTap.toggle()} // ← If I comment out this line,the swipe motion work well.
.gesture(DragGesture().onChanged(isOn ? onChangedOn(value:) : onChangedOff(value:))
.onEnded(isOn ? onEndOn(value:) : onEndOff(value:))
)
}
}
.frame(width: 60, height: 120)
}
}
func onChangedOff(value: DragGesture.Value){
if value.translation.height < 0 && offset >= -60{
offset = value.translation.height
}
}
func onChangedOn(value: DragGesture.Value){
if offset <= 0{
offset = value.translation.height - 60
}
}
func onEndOff(value: DragGesture.Value){
if offset < -40 {
offset = -60
isOn = true
}else{
offset = 0
}
}
func onEndOn(value: DragGesture.Value){
if offset > -20 {
offset = 0
isOn = false
}else{
offset = -60
}
}
}
Xcode: Version 12.3
iOS: 14.0
You can use simultaneousGesture
:
Circle()
.fill(isOn ? Color.blue : Color.green )
.frame(width: 60, height: 60)
.offset(y:offset)
.onTapGesture {isOnTap.toggle()}
.simultaneousGesture(DragGesture().onChanged(isOn ? onChangedOn(value:) : onChangedOff(value:))
.onEnded(isOn ? onEndOn(value:) : onEndOff(value:))
)
Also, you can adjust the minimumDistance
of the DragGesture
(by default it's 10
):
DragGesture(minimumDistance: 10)