Let's make a simple custom "infinite" spinner.
SwiftUI provides ProgressView
as the prototypical container for this with ProgressViewStyle
as a means of customizing the way to present the progress.
To make our spinner infinitely spin, we'll use a linear animation, repeat it forever, start it at a rotation effect of 0 and move it to 360 degrees, as soon as the spinner appears.
Simple!
Now let's put it inside a NavigationView
🔥:
We see the spinner bouncing up and down as it spins. Any clue what's going on or how to address the issue (while preserving a respect for the fundamentals, eg. ProgressView
to display progress and ProgressViewStyle
to customize it)?
struct SimplePreview: PreviewProvider, View {
static var previews = Self()
@State
private var isAnimating = false
var body: some View {
NavigationView {
ProgressView().progressViewStyle(SymbolicStyle())
}
}
public struct SymbolicStyle: ProgressViewStyle {
@State
private var isAnimating = false
public func makeBody(configuration: Configuration) -> some View {
Image(systemName: "circle.hexagonpath.fill")
.rotationEffect(self.isAnimating ? .degrees(360) : .zero)
.onAppear {
withAnimation(.linear(duration: 1).repeatForever(autoreverses: false)) {
self.isAnimating = true
}
}
}
}
}
You can replace .onAppear
with .task
in order to start the animation in a separate context where it does not get mixed up with other unreleated layout events.