Swiftui: Animation Inside Navigationview

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.

demo

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



Leave a reply



Submit