Reputation: 214
I have an imageview in SwiftUI and i want to scale the view to higher size for fraction of second and return to it's normal size. How can i do this in SwiftUI?
Image("disagreeSmall")
.scaleEffect(scale)
.animation(.easeIn(duration: 0.15), value: selectedRating)
Upvotes: -1
Views: 523
Reputation: 21730
If you are able to use functionality that was only introduced in iOS 17 then there are two easy ways to achieve this animation:
1. Use a .symbolEffect
For SF symbols, the .bounce
effect scales up and then down again:
Image(systemName: "hand.thumbsdown.fill")
.symbolEffect(.bounce, value: selectedRating)
2. Use a PhaseAnimator
A PhaseAnimator
can be used to perform chained animations:
PhaseAnimator([false, true], trigger: selectedRating) { phase in
Image("disagreeSmall")
.scaleEffect(phase ? 1.1 : 1.0)
} animation: { phase in
phase ? .easeIn(duration: 0.15) : .easeOut(duration: 0.15)
}
If you need to support older iOS versions then you could use other mechanisms to chain the animations. This is how it could be done using the animation completion callback outlined in the answer to SwiftUI withAnimation completion callback:
// Credit to Centurion for the AnimatableModifier solution:
// https://stackoverflow.com/a/62855108/20386264
struct AnimationCompletionCallbackCGFloat: ViewModifier, Animatable {
var targetValue: CGFloat
var completion: () -> ()
init(animatedValue: CGFloat, completion: @escaping () -> ()) {
self.targetValue = animatedValue
self.completion = completion
self.animatableData = animatedValue
}
var animatableData: CGFloat {
didSet {
checkIfFinished()
}
}
func checkIfFinished() -> () {
if (animatableData == targetValue) {
DispatchQueue.main.async {
self.completion()
}
}
}
func body(content: Content) -> some View {
content
}
}
Image("disagreeSmall")
.scaleEffect(scale)
.onChange(of: selectedRating) { newVal in // pre iOS 17
withAnimation(.easeIn(duration: 0.15)) {
scale = 1.1
}
}
.modifier(
AnimationCompletionCallbackCGFloat(animatedValue: scale) {
withAnimation(.easeOut(duration: 0.15)) {
scale = 1.0
}
}
)
Upvotes: 0