SwiftUI 反向动画延迟移除
Posted
技术标签:
【中文标题】SwiftUI 反向动画延迟移除【英文标题】:SwiftUI inverse animation delay on removal 【发布时间】:2020-06-01 21:40:47 【问题描述】:我正在尝试在 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))
当你运行这个并点击按钮时,蓝条移入,然后红条移入。再次点击按钮,蓝条移出,然后红条移出。我想要的是当你点击删除按钮时,红色条移出,然后蓝色条移出,与条进入的方式相反。在这段代码中,我相信三元组不起作用,因为设置了动画当创建 Rectangle 并且之后延迟不能改变。我可能错了,但无论哪种方式都有办法做我想做的事吗?
【问题讨论】:
【参考方案1】:这里有一个解决方案。使用 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
【讨论】:
【参考方案2】:您不能根据状态值更改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
【讨论】:
以上是关于SwiftUI 反向动画延迟移除的主要内容,如果未能解决你的问题,请参考以下文章