I'm trying to create animated button that will be triggered by long press.
Animation must be only when long press is going.
Why in this code topG update is never triggered?
struct ContentView: View {
var body: some View {
MyCustomButton(text: "My button") { print("button pressed") }
.padding(100)
}
}
struct MyCustomButton: View {
let text: LocalizedStringKey
var action: () -> ()
@State private var Hpress = false
@GestureState private var topG = false
private let radius: CGFloat = 10
var body: some View {
Text(text)
.padding(.horizontal, 30)
.padding(.vertical, 10)
.allowsHitTesting(true)
.background { Bg() }
.animation(.easeInOut.speed(0.5), value: topG)
.scaleEffect(topG ? 1.2 : 1)
.gesture(
LongPressGesture(minimumDuration: 1.5, maximumDistance: 1)
.updating($topG) { cstate, gstate, trantion in
gstate = cstate
}
.onEnded { value in
Hpress.toggle()
action()
}
)
.animation( .spring(response: 0.6, dampingFraction: 0.6), value: topG)
}
func Bg() -> some View {
RoundedRectangle(cornerRadius: radius)
.fill(Color.black.opacity(0.4))
.overlay{
ZStack {
RoundedRectangle(cornerRadius: radius, style: .continuous)
.foregroundColor(.gray.opacity(0.1))
RoundedRectangle(cornerRadius: radius, style: .continuous)
.trim(from: 0, to: topG ? 1 : 0)
.stroke(style: StrokeStyle(lineWidth: 3, lineCap: .round))
.rotation(Angle(degrees: 180))
}
}
}
}
In the end I want to get the following:
- "pressed" animation starts when touch starts.
- Execute action must be after 0.7. But temporary for debugging purposes I set it to 1.5sec instead of 0.7
- Action triggered only once as soon as the finger is held down for more than 1.5(or 0.7s~) seconds.
- Action must be executed even user didn't lift finger
- Release animation must be started in case of
action()
didn't called - Release animation is faster than main animation. Duration must be ~0.2sec
- If action is not called - button reverts to original state with animation.
- If pressed and action was called also reverts to original state.