SwiftUI逆动画移除延迟

时间:2020-06-01 21:40:47

标签: swift swiftui

我正在尝试在SwiftUI中编排动画。我希望两个彩色条在它们之间具有延迟的情况下进入视图,然后在延迟被切换的情况下移出视图,以使删除与插入相反。

我想我理解下面的代码为什么不起作用,但是我不知道如何使它满足我的需要:

import SwiftUI

struct TestAnimControl: View {
    @State var show: Bool = false
    @State var reverseDelay: Bool = false

    var body: some View {
        VStack {
            Button(action:{
                self.show.toggle()
            }) {
                Text("Animate")
                    .font(.largeTitle)
            }
            if show {
                Rectangle()
                    .foregroundColor(.blue)
                    .frame(height: 100)
                    .transition(.move(edge: .trailing))
                    .animation(Animation.spring().delay(show ? 0.3 : 0.5))
                Rectangle()
                    .foregroundColor(.red)
                    .frame(height: 100)
                    .transition(.move(edge: .trailing))
                    .animation(Animation.spring().delay(show ? 0.5 : 0.3))
            }
        }
    }
}

运行此命令并单击按钮时,蓝色条移入,然后红色条移入。再次单击按钮,蓝色条移出,然后红色条移出。我想要的是,当您按下要删除的按钮时,红色的条移出,然后蓝色的条移出,与条进入的方式相反。在此代码中,我相信三元操作无效,因为设置了动画创建矩形后,延迟将不会更改。我可能是错的,但是有一种方法可以做我想做的事吗?

2 个答案:

答案 0 :(得分:2)

这是一个解决方案。使用Xcode 11.4 / iOS 13.4进行了测试

demo

struct TestAnimControl: View {
    @State var show: Bool = false
    @State var reverseDelay: Bool = false

    @State var blueDelay = 0.3
    @State var redDelay = 0.5
    var body: some View {
        VStack {
            Button(action:{
                self.show.toggle()
            }) {
                Text("Animate")
                    .font(.largeTitle)
            }
            if show {
                Rectangle()
                    .foregroundColor(.blue)
                    .frame(height: 100)
                    .transition(.move(edge: .trailing))
                    .animation(Animation.spring().delay(blueDelay))//(show ? 0.3 : 0.5))
                    .onAppear { self.blueDelay = 0.5 }
                    .onDisappear { self.blueDelay = 0.3 }
                Rectangle()
                    .foregroundColor(.red)
                    .frame(height: 100)
                    .transition(.move(edge: .trailing))
                    .animation(Animation.spring().delay(redDelay))//(show ? 0.5 : 0.3))
                    .onAppear { self.redDelay = 0.3 }
                    .onDisappear { self.redDelay = 0.5 }
            }
        }
    }
}

答案 1 :(得分:1)

您无法根据状态值更改delay的值,因为Animation结构被标记为@frozen,对属性观察者没有影响-状态属性(请检查https://docs.swift.org/swift-book/ReferenceManual/Attributes.html )。正确的方法是使用DispatchQueue.main.asyncAfter(deadline:_:)指定每个延迟。这是我的示例代码...

struct ContentView: View {
    @State var blue = false
    @State var red = false

    var body: some View {
        VStack {
            Button(action:{
                let redDelay = self.red ? 0.3 : 0.5
                DispatchQueue.main.asyncAfter(deadline: .now() + redDelay) {
                    self.red.toggle()
                }
                let blueDelay = self.blue ? 0.5 : 0.3
                DispatchQueue.main.asyncAfter(deadline: .now() + blueDelay) {
                    self.blue.toggle()
                }
            }) {
                Text("Animate")
                    .font(.largeTitle)
            }
            if blue {
                Rectangle()
                    .foregroundColor(.blue)
                    .frame(height: 100)
                    .transition(AnyTransition.move(edge: .trailing))
                    .animation(Animation.spring())
            }
            if red {
                Rectangle()
                    .foregroundColor(.red)
                    .frame(height: 100)
                    .transition(AnyTransition.move(edge: .trailing))
                    .animation(Animation.spring())
            }
        }
        .animation(.spring())
    }
}

谢谢。 X_X