我正在尝试在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))
}
}
}
}
运行此命令并单击按钮时,蓝色条移入,然后红色条移入。再次单击按钮,蓝色条移出,然后红色条移出。我想要的是,当您按下要删除的按钮时,红色的条移出,然后蓝色的条移出,与条进入的方式相反。在此代码中,我相信三元操作无效,因为设置了动画创建矩形后,延迟将不会更改。我可能是错的,但是有一种方法可以做我想做的事吗?
答案 0 :(得分:2)
这是一个解决方案。使用Xcode 11.4 / iOS 13.4进行了测试
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