ios - SwiftUI 中的动态转换

标签 ios swift swiftui swiftui-animation

我希望能够根据状态转换使用不同的转换。例如,如果我从 .one => .three 开始,我想在删除时淡出 ViewOne。如果我从 .one => .two 开始,我想在删除时将 ViewOne 向左移动。现在我有这样的东西(显然,它只适用于从 .one => .two 的转换):

ZStack {
    if state == .one {
        ViewOne()
            .transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)))
    }

    if state == .two {
        ViewTwo()
            .transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)))
    }

    if state == .three {
        ViewThree()
            .transition(.asymmetric(insertion: .opacity, removal: .identity))
    }
}
如何根据状态动态更改转换?
更新:
这是一个更完整的例子:
enum Screen {
    case susi, onboarding, home
}

struct ContentView: View {
    @State var screen: Screen = .susi
    @State var transition: AnyTransition = .asymmetric(insertion: .identity, removal: .move(edge: .leading))
    
    var body: some View {
        ZStack {
            if screen == .susi {
                ViewOne()
                    .transition(transition)

            }
            if screen == .onboarding {
                ViewTwo()
                    .transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)))
            }
            if screen == .home {
                ViewThree()
                    .transition(.asymmetric(insertion: .opacity, removal: .identity))
            }
        }
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                withAnimation(.default) {
                    self.transition = .asymmetric(insertion: .identity, removal: .opacity)
                    self.screen = .home
                }
            }
        }
    }
}

最佳答案

对于那些遇到相同问题的读者,一种解决方案是切换 id View 的属性。围绕 SO 进行的一些搜索使我采用了这种技术,它显然会重置 View 的动画。

import SwiftUI

enum Screen {
    case susi, onboarding, home
}

struct ContentView: View {
    @State var screen: Screen = .susi
    @State var transition: AnyTransition = .move(edge: .leading)
    @State var viewId = UUID().uuidString
    
    var body: some View {
        ZStack {
            if screen == .susi {
                ViewOne()
                    .transition(transition)

            }
            if screen == .onboarding {
                ViewTwo()
                    .transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .trailing)))
            }
            if screen == .home {
                ViewThree()
                    .transition(.asymmetric(insertion: .opacity, removal: .move(edge: .bottom)))
            }
        }
        .id(viewId)
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                withAnimation(.default) {
                    self.screen = .onboarding
                }
                
                DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                    withAnimation(.default) {
                        self.screen = .susi
                    }
                    
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                        self.transition = .opacity
                        self.viewId = UUID().uuidString
                        
                        withAnimation(.default) {
                            self.screen = .home
                        }
                        
                        DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                            self.transition = .move(edge: .top)
                            self.viewId = UUID().uuidString
                            
                            withAnimation(.default) {
                                self.screen = .susi
                            }
                            
                            DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                                self.transition = .move(edge: .leading)
                                self.viewId = UUID().uuidString
                                
                                withAnimation(.default) {
                                    self.screen = .onboarding
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
我最终修改了 idViewOne而不是整个 ZStack,因为担心这样做会在 future 产生一些意想不到的 SwiftUI 怪癖。相同的技术,只是将其应用于不同的 View 。

关于ios - SwiftUI 中的动态转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66978328/

相关文章:

SwiftUI:如何更改 slider 的范围?

ios - 如何解决此错误 "Cannot invoke getObejectAtPath with argument list type of string"

ios - SwiftUI:通过 View 组合实现代码重用

ios - 将 facebook 聊天 API 集成到 iOS 应用程序中

swift - 如何使用 Swift 在 iOS 应用程序中创建热点网络

ios - 从嵌入式 View Controller 传回数据

ios - 如何在 iOS 中将字符串变量分配给标签或文本字段

ios - 在 SwiftUI 中从 TabView 获取所选标签索引的方法

iphone - 推式转场场景有效,模态转场场景不行?

ios - FirebaseUI/PhoneAuth/FirebasePhoneAuthUI/FUICodeField.xib :-1: Failed to find or create execution context for description