Given the following struct
:
struct PeopleList : View {
@State var angle: Double = 0.0
@State var isAnimating = true
var foreverAnimation: Animation {
Animation.linear(duration: 2.0)
.repeatForever()
}
var body: some View {
Button(action: {}, label: {
Image(systemName: "arrow.2.circlepath")
.rotationEffect(Angle(degrees: self.isAnimating ? self.angle : 0.0))
.onAppear {
withAnimation(self.foreverAnimation) {
self.angle += 10.0
}
}
})
}
}
I was hoping that the Image
would rotate clockwise and repeat until self.isAnimating
is false
although it's only animated once.
To make our animation repeat, we use . repeatForever() . The default behavior of repeat forever is autoreverse, that's mean our animation will scale from 1 to 0.5 then 0.5 back to 1, creating a seamless loop of animation.
SwiftUI has built-in support for animations with its animation() modifier. To use this modifier, place it after any other modifiers for your views, tell it what kind of animation you want, and also make sure you attach it to a particular value so the animation triggers only when that specific value changes.
SwiftUI uses Core Animation for rendering by default, and its performance is great for most animations. But if you find yourself creating a very complex animation that seems to suffer from lower framerates, you may want to utilize the power of Metal, which is Apple's framework used for working directly with the GPU.
Here is possible solution for continuous progressing on appear & start/stop. Tested with Xcode 11.4 / iOS 13.4.
struct PeopleList : View {
@State private var isAnimating = false
@State private var showProgress = false
var foreverAnimation: Animation {
Animation.linear(duration: 2.0)
.repeatForever(autoreverses: false)
}
var body: some View {
Button(action: { self.showProgress.toggle() }, label: {
if showProgress {
Image(systemName: "arrow.2.circlepath")
.rotationEffect(Angle(degrees: self.isAnimating ? 360 : 0.0))
.animation(self.isAnimating ? foreverAnimation : .default)
.onAppear { self.isAnimating = true }
.onDisappear { self.isAnimating = false }
} else {
Image(systemName: "arrow.2.circlepath")
}
})
.onAppear { self.showProgress = true }
}
}
UPDATE: There is a backspin involved while stopping the animation which is solved with this solution.
I think its this what you are looking for:
struct PeopleList : View {
@State var angle: Double = 0.0
@State var isAnimating = false
var foreverAnimation: Animation {
Animation.linear(duration: 2.0)
.repeatForever(autoreverses: false)
}
var body: some View {
Button(action: {}, label: {
Image(systemName: "arrow.2.circlepath")
.rotationEffect(Angle(degrees: self.isAnimating ? 360.0 : 0.0))
.animation(self.foreverAnimation)
.onAppear {
self.isAnimating = true
}
})
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With