I have whittled this issue down as part of a larger project that has a lot of complex animations that were all working well until I wrapped the view in a NavigationView. After that all of the views decided they wanted to trigger all sorts of positional animation, and I had views all sliding into place when the view showed up. A lot of these animations were explicit and tied to events, so there should have been no animation at all. I went removed all the implicit animations and the problem persisted. It seems that is a view has an animation attached to it, then the NavigationView will positionally animate it onAppear
Here is a minimum example that reproduces it:
struct ContentView: View {
@State var opacity = 0.5
var body: some View {
NavigationView {
Circle()
.opacity(opacity)
.animation(.default)
}
}
}
In this example there is not a single animation trigger yet the NavigationView still animates it in. Removing the NavigationView will make it act as normal.
I am assuming it is a bug in the NavigationView implementation where they probably using slide transitions to segue into the linked views, which is applying it to its sub views.
Does anyone know or can figure out a workaround for this?
Similar but questions with unsuitable answers are: What might be causing this animation bug with SwiftUI and NavigationView?
SwiftUI: Broken explicit animations in NavigationView?
Current as of iOS 14.2 Xcode 12.2
Edit: It appears the issues lies with having more than one view under a ZStack or overlay. In the following code, if you comment out the Color.black view you will see the animation digresses into onAppear transitions for the animated view (circle)
import SwiftUI
struct ProgressCircle: View {
@State var show = false
let progress: Double
let foreColor: Color
let backgroundColor: Color
let strokeWidth: Double
init(foregroundColor: Color, backgroundColor: Color, strokeWidth: Double, progress: Double) {
self.foreColor = foregroundColor
self.backgroundColor = backgroundColor
self.strokeWidth = strokeWidth
self.progress = progress
}
var body: some View {
ZStack {
Circle()
.stroke(backgroundColor, style:
StrokeStyle(lineWidth: CGFloat(strokeWidth), lineCap: .round, lineJoin: .round))
Circle()
.trim(from: 0 , to: self.show ? CGFloat(max(self.progress, 0.01)) : 0.01)
.stroke(foreColor,
style: StrokeStyle(lineWidth: CGFloat(strokeWidth), lineCap: .round, lineJoin: .round))
.rotationEffect(.degrees(-90))
.animation(.easeInOut(duration: 2), value: self.show)
.animation(.easeInOut(duration: 2), value: self.progress)
.onAppear {
self.show = true
}
}
}
}
struct ProgressCircle_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
ScrollView {
ZStack {
// Color.black
ProgressCircle(
foregroundColor: Color.black,
backgroundColor: Color.red,
strokeWidth: 15,
progress: 0.7)
.frame(width: 200, height: 200)
.background(Color.blue)
}
}
.navigationTitle("Hello")
}
}
}