Dictator
Dictator

Reputation: 133

How to disable position animation in SwiftUI?

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

Upvotes: 0

Views: 2360

Answers (2)

Andrew_STOP_RU_WAR_IN_UA
Andrew_STOP_RU_WAR_IN_UA

Reputation: 11426

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/

Upvotes: 0

vacawama
vacawama

Reputation: 154583

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
        }
        
    }
}

Upvotes: 3

Related Questions