SwiftUI: Animation Inside NavigationView
The onAppear is called too early when view frame is zero being in NavigationView, so animation is applied to change from zero to value.
Here is valid workaround. Tested with Xcode 12.4 / iOS 14.4
var body: some View {
ZStack() {
Color.clear
Rectangle()
.frame(width: animate ? finalRect.width: currentRect.width, height: animate ? finalRect.height: currentRect.height, alignment: .center)
.animation(animation, value: animate)
.onAppear {
DispatchQueue.main.async {
// << postpone till end of views construction !!
animate = true
}
}
}
}
Note: almost any why question can be answered only by Apple... maybe it is a bug, maybe an implementation specifics.
SwiftUI: Broken explicit animations in NavigationView?
Here is fixed part (another my answer with explanations is here).
Tested with Xcode 12 / iOS 14.
struct EscapingAnimationTest_Inner: View {
@State var degrees: CGFloat = 0
var body: some View {
Circle()
.trim(from: 0.0, to: 0.3)
.stroke(Color.red, lineWidth: 5)
.rotationEffect(Angle(degrees: Double(degrees)))
.animation(Animation.linear(duration: 1).repeatForever(autoreverses: false), value: degrees)
.onAppear() {
DispatchQueue.main.async { // << here !!
degrees = 360
}
}
}
}
Update: the same will be using withAnimation
.onAppear() {
DispatchQueue.main.async {
withAnimation(Animation.linear(duration: 1).repeatForever(autoreverses: false)) {
degrees = 360
}
}
}
SwiftUI animation problem with a binding to a StateObject inside a NavigationView
To be honest with you, I am not sure why, but utilizing the animation modifier on the RectView
allows the animation to occur without any issues.
struct RectView: View {
@Binding var isRed: Bool
var body: some View {
Rectangle()
.fill(isRed ? Color.red : Color.gray)
.frame(width: 75, height: 75, alignment: .center)
.animation(.easeOut(duration: 1), value: isRed)
.onTapGesture { isRed.toggle() }
}
}
screen recording example
Transitions not working inside NavigationView
I think you just wanted this - animatable transition
struct InitialView: View {
@State var displayView = false
var body: some View {
NavigationView { // << just root view, not important
ZStack { // << owner container !!
if displayView {
NextView(displayView: $displayView)
.transition(.slide)
} else {
Button("Tap to continue") {
displayView = true
}
}
}
.animation(.default, value: displayView) // << animation !!
}
}
}
Tested with Xcode 13.4 / iOS 15.5
SwiftUI, Navigation view and animated transitions in destination. VStack works but List does not
Moving the destination to a different struct fixes the issue.
struct RectView: View {
@State var fff: Bool = false
var body: some View {
ZStack {
if fff {
RoundedRectangle(cornerRadius: 100) .foregroundColor(.blue)
.transition(.asymmetric(insertion: .move(edge: .bottom), removal: .move(edge: .top)))
.animation(.easeIn)
} else {
RoundedRectangle(cornerRadius: 100) .foregroundColor(.purple)
.transition(.asymmetric(insertion: .move(edge: .bottom), removal: .move(edge: .top)))
.animation(.easeIn)
}
Button(action: {
fff.toggle()
}, label: {
Text("Button")
})
}
}
}
Why does an animation in a NavigationView starts from the top left corner?
Why does an animation in a NavigationView starts from the top left corner?
Because implicit animation affects all animatable properties, including position, which on creation time is CGPoint.zero
(ie. top-left corner).
Such cases are solved by linking animation to dependent state value, thus it activates only when state changed, so all animatable properties not affected.
Here is possible variant for your case. Tested with Xcode 12.1 / iOS 14.1.
struct ContentView: View {
@State var show = false
var body: some View {
GeometryReader { gp in
NavigationView {
HStack {
Text("Hello, world!")
.padding()
.background(Color.blue)
.offset(x: 0, y: show ? 0 : -gp.size.height / 2)
.animation(Animation.easeOut.delay(0.6), value: show)
.onAppear {
self.show = true
}
.navigationTitle("Why?")
}
}
}
}
}
SwiftUI rotation animation has unexpected translation
Declare .backgound(Color.red) before declaring animation so that it will animate background as well.
And for issue when using navigation view, see the code : -
VStack{
Spacer()
Image("FilmCircle")
.resizable()
.scaledToFit()
.background(Color.red)
.frame(width: 100, height: 100)
.rotationEffect(Angle(degrees: isAnimating ? 360 : 0), anchor: .center)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
withAnimation(.linear(duration: 2).repeatForever(autoreverses: false)) {
isAnimating = true
}
}
}
Spacer()
}
Hope you found this helpful.
Related Topics
How to Add Custom Text in Nsdateformatter's Format String
Com.Facebook.Sdk Error 2 on iOS
Xcode 5/iOS 7 - Localization Not Working in Simulator
Using Sysctlbyname() from Swift
Apple MACh-O Linker (Id) Warning:Building for MACosx, But Linking Against Dylib Built for iOS
Uitableviewcellaccessorycheckmark and Autolayout Constraints
Programmatically Highlight Uibarbuttonitem
Simple Uitableview in Swift - Unexpectedly Found Nil
Enable Uialertaction of Uialertcontroller Only After Input Is Validated
iOS 7 When Rotating View in Tab Bar, Right Side of View Is Not Clickable
Static VS Class as Class Variable/Method (Swift)
How to Expose Existing Property on Obj-C Class Using an Extension Protocol in Swift