Simple and regular approach to animate a bump effect for a button but not simple in SwiftUI.
I'm trying to change scale
in tapGesture
modifier, but it doesn't have any effect. I don't know how to make chain of animations, probably because SwiftUI doesn't have it. So my naive approach was:
@State private var scaleValue = CGFloat(1)
...
Button(action: {
withAnimation {
self.scaleValue = 1.5
}
withAnimation {
self.scaleValue = 1.0
}
}) {
Image("button1")
.scaleEffect(self.scaleValue)
}
Obviously it doesn't work and buttons image get last scale value immediately.
My second thought was to change scale to 0.8
value on hold
event and then after release
event make scale to 1.2
and again after few mseconds change it to 1.0
. I guess this algorithm should make nice and more natural bump effect. But I couldn't find suitable gesture
struct in SwiftUI to handle hold-n-release
event.
P.S. For ease understanding, I will describe the steps of the hold-n-release
algorithm:
- Scale value is
1.0
- User touch the button
- The button scale becomes
0.8
- User release the button
- The button scale becomes
1.2
- Delay
0.1
sec - The button scale go back to default
1.0
UPD: I found a simple solution using animation delay
modifier. But I'm not sure it's right and clear. Also it doens't cover hold-n-release
issue:
@State private var scaleValue = CGFloat(1)
...
Button(action: {
withAnimation {
self.scaleValue = 1.5
}
//
// Using delay for second animation block
//
withAnimation(Animation.linear.delay(0.2)) {
self.scaleValue = 1.0
}
}) {
Image("button1")
.scaleEffect(self.scaleValue)
}
UPD 2:
I noticed in solution above it doesn't matter what value I pass as argument to delay
modifier: 0.2
or 1000
will have same effect. Perhaps it's a bug
Yes, it looks like a bug but after my experimenting I found that you can do so
I've post a demo at https://youtu.be/kw4EIOCp78g
There is another strange thing if we move and scale the second Image to the first then it will not be shown without
.frame(width: 100, height: 100)
.Nice and clean
swiftUI
solution:however, you also need to add this code snippet to the project: