How to disable position animation in SwiftUI?

2k views Asked by At

I want to scroll a VStack programmatically and some of child views can be animated independently, but when changing the VStack's offset the animated child view move to its final position witth animation, that's not what I want and how to disable animating this position changes? Here is my demo code,

import SwiftUI

struct ContentView: View {
    @State var angle:Double = 0
    @State var offset = 0
    var body: some View {
            LazyVStack {
                ForEach((0..<100)) { i in
                    if i == 25 {
                        Rectangle()
                            .frame(width: 30, height: 30)
                            .animation(.none)
                            .rotationEffect(.degrees(angle), anchor: .center)
                            .animation(Animation.linear(duration: 3).repeatForever(autoreverses: false))
                            .onAppear {
                                angle = 360
                            }
                    } else {
                        Text("number \(i)")
                    }
                }
            }
            .offset(y: CGFloat(offset))
            .animation(.none)
            .onAppear {
                offset = 200
            }
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

and the effect, enter image description here

2

There are 2 answers

1
vacawama On BEST ANSWER

Try the following (tested in Xcode 12.0.1, iOS14):

Use an explicit animation call when setting the angle:

import SwiftUI

struct ContentView: View {
    @State var angle:Double = 0
    @State var offset = 0
    var body: some View {
        LazyVStack {
            ForEach((0..<100)) { i in
                if i == 25 {
                    Rectangle()
                        .frame(width: 30, height: 30)
                        .rotationEffect(.degrees(angle), anchor: .center)
                        .onAppear {
                            withAnimation(Animation.linear(duration: 3).repeatForever(autoreverses: false)) {
                                angle = 360
                            }
                        }
                } else {
                    Text("number \(i)")
                }
            }
        }
        .offset(y: CGFloat(offset))
        .onAppear {
            offset = 200
        }
        
    }
}
0
Andrew_STOP_RU_WAR_IN_UA On
public extension View {
    func animationMovementDisable() -> some View  {
        self
            .transaction { transaction in
                transaction.animation = nil
            }
    }
}

based on article: https://www.avanderlee.com/swiftui/disable-animations-transactions/