Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delay a transition in SwiftUI

How can I delay a transition? I want to click on a button and then a view should transition with a delay.

I have the following code but it is not properly synchronized.

struct ContentView: View {
    @State var showOne = true


    var body:some View{
        VStack{
            if showOne{
                HStack{
                    Spacer()
                    Text("One")
                    Spacer()
                }
                .animation(Animation.default.delay(2))
                .background(Color.red)
                .transition(.slide)
            }else{
                HStack{
                    Spacer()
                    Text("Two")
                    Spacer()
                }
                .background(Color.blue)
                .animation(Animation.default.delay(1))
                .transition(.slide)
            }
            Button("Toggle"){
                withAnimation(){
                    self.showOne.toggle()
                }
            }
        }
    }
}
like image 428
simibac Avatar asked Feb 17 '20 22:02

simibac


People also ask

How to add delay to animation SwiftUI?

When you create any animation – implicitly, explicitly, or with bindings – you can attach modifiers to that animation to adjust the way it works. For example, if you want an animation to start after a certain number of seconds you should use the delay() modifier.

What is withAnimation SwiftUI?

withAnimation() takes a parameter specifying the kind of animation you want, so you could create a three-second linear animation like this: withAnimation(.linear(duration: 3)) Explicit animations are often helpful because they cause every affected view to animate, not just those that have implicit animations attached.

How do I add animations to SwiftUI?

SwiftUI has built-in support for animations with its animation() modifier. To use this modifier, place it after any other modifiers for your views, tell it what kind of animation you want, and also make sure you attach it to a particular value so the animation triggers only when that specific value changes.


1 Answers

If you add an explicit id it works as you would like. Note, I made only one animation delay to make it a little more obvious that this is working.

struct ContentView: View {
    @State var showOne = true
    var body:some View {
        VStack {
            if showOne {
                HStack {
                    Spacer()
                    Text("One")
                    Spacer()
                }
                .background(Color.red)
                .id("one")
                .animation(Animation.default)
                .transition(.slide)
            } else {
                HStack {
                    Spacer()
                    Text("Two")
                    Spacer()
                }
                .background(Color.blue)
                .id("two")
                .animation(Animation.default.delay(2))
                .transition(.slide)
            }
            Button("Toggle") {
                withAnimation {
                    self.showOne.toggle()
                }
            }
        }
    }
}

I've found an explicit id to be helpful most of the time I want to use a transition. In your example, not using the id can cause the text to change before the background. This would seem to be a bug, and I recommend filing feedback on it.

like image 55
arsenius Avatar answered Oct 19 '22 21:10

arsenius