Home > Enterprise >  Override animation SwiftUI
Override animation SwiftUI

Time:10-07

So basically i have an animation which indicates how long the user has to perform a certain action. This can take up to two days. If the user did perform the action before the two days, the animation should restart. As of now, the first part works perfectly. However, when the animation should restart but has not finished yet, i can not cancel it which interfers with the new animation.

This is called on animation setup or restart (set the circle to its inital value and then animate slowly to zero)

self.vm.circle = duration / 172800 // 2 days (in seconds)
withAnimation(.linear(duration: duration)) {
    self.vm.circle = 0
}

And this is how i use it:

Circle()
    .trim(from: 0, to: vm.circle)

How can i cancel or override my "old" animation ?

Edit: I have set up a simple example to display the problem.

@State var flag = true

var body: some View {
    VStack {
        Spacer()
        Text("Scale Me")
            .scaleEffect(flag ? 1 : 3)
        Spacer()
        Button {
            flag = true
            withAnimation(.linear(duration: 5)) {
                flag = false
            }
        } label: {
            Text("Scale")
        }
        Spacer()
    }
}

enter image description here

CodePudding user response:

You can wrap assigning true to flag in an animation block and in that animation block you add your existing animation block.

It will work even though I don't know if this is the correct way.

struct ContentView: View {
    @State var flag = true

    var body: some View {
        VStack {
            Spacer()
            Text("Scale Me")
                .scaleEffect(flag ? 1 : 3)
            Spacer()
            Button {
                withAnimation {
                    flag = true
                    withAnimation(.linear(duration: 5)) {
                        flag = false
                    }
                }
            } label: {
                Text("Scale")
            }
            Spacer()
        }
    }
}

EDIT: Found a better solution from https://www.hackingwithswift.com/forums/swiftui/instantly-reset-state-of-animation/4494

Basically you add an id to the text and create a new id every time you click the button:

struct ContentView: View {
    @State var flag = true
    @State var id = UUID() {
        didSet {
            flag = true
        }
    }

    var body: some View {
        VStack {
            Spacer()
            Text("Scale Me")
                .scaleEffect(flag ? 1 : 3)
                .id(id)
            Spacer()
            Button {
                id = .init()
                withAnimation(.linear(duration: 5)) {
                    flag = false
                }
            } label: {
                Text("Scale")
            }
            Spacer()
        }
    }
}
  • Related