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 反向动画延迟移除的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 动画:如何延迟重复动画

SwiftUI 动画和随后的反向动画到原始状态

SwiftUI ForEach 没有动画延迟

SwiftUI:如何使用延迟在两个图像之间设置动画过渡?

延迟 SwiftUI 中的重复动画,在完整的自动反转重复周期之间

Swiftui NavigationView 计时器延迟