SwiftUI 中的动态转换

Posted

技术标签:

【中文标题】SwiftUI 中的动态转换【英文标题】:Dynamic transitions in SwiftUI 【发布时间】:2021-04-07 01:11:47 【问题描述】:

我希望能够根据状态转换使用不同的转换。例如,如果我从 .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
                
            
        
    

【问题讨论】:

你能显示该州的代码吗? 我添加了一个完整的示例,说明了所需(但不工作)的行为。 这是否回答了您的问题***.com/questions/61340717/…? 这是一个非常好的问题。据我了解,在创建视图时将转换定义为视图,因此在创建视图后更改转换实际上会触发旧视图的removal 转换(这是在将其更改为之前定义的转换)褪色或移动)因此无法更新视图的转换属性,直到下一次删除。我也对可行的解决方案感到好奇。 【参考方案1】:

对于阅读此问题的人来说,一种解决方案是切换视图的id 属性。围绕 SO 进行的一些搜索将我引向了这种技术,它显然会重置视图的动画。

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
                                
                            
                        
                    
                
            
        
    

我最终改为修改 ViewOneid 而不是整个 ZStack,因为担心这样做会在路上产生一些意想不到的 SwiftUI 怪癖。相同的技术,只是将其应用于不同的视图。

【讨论】:

以上是关于SwiftUI 中的动态转换的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 中的动态过滤器(谓词)

如何根据相关对象转换 SwiftUI 获取请求结果?

@FetchRequest 中的 SwiftUI 和动态 NSSortDescriptors

延迟 SwiftUI 中的转换

SwiftUI 中的动态列表从 JSON 和 Textfield 更新

SwiftUI:将选取器选择设置为动态数组中的最后一个