SwiftUI:动画过渡

Posted

技术标签:

【中文标题】SwiftUI:动画过渡【英文标题】:SwiftUI: Animate Transitions 【发布时间】:2021-07-15 22:39:45 【问题描述】:

如何在不同视图之间设置幻灯片过渡动画?

在下面的示例代码中,我创建了一个 Picker,用于选择要显示的视图,我的目标是获得一个看起来类似于 NavigationLink 转换的转换。 目前它根本没有动画。 如果我将 .animation(.easeInOut(duration: 2)) 修饰符添加到 ZStack ,它会为淡入淡出动画设置 2 秒的动画,但我不明白为什么。

struct ContentView: View 

    enum WhichScreen: String, CaseIterable 
        case red, blue, green, yellow
    

    @State private var whichScreen = WhichScreen.red

    var body: some View 
        VStack 
            Picker("screen", selection: $whichScreen.animation()) 
                ForEach(WhichScreen.allCases, id: \.self)  value in
                    Text(value.rawValue).tag(value)
                
            
            .pickerStyle(SegmentedPickerStyle())
            ZStack 
                Color.black
                switch whichScreen 
                case .red:
                    Color.red
                case .blue:
                    Color.blue
                case .green:
                    Color.green
                case .yellow:
                    Color.yellow
                
            
            .transition(.slide)
        
    

【问题讨论】:

【参考方案1】:

您真的需要黑色的 ZStack(在您的示例 sn-p 中永远不可见)吗?没有它,转换开箱即用(在模拟器中,而不是在 SwiftUI 预览中):

struct ContentView: View 

    enum WhichScreen: String, CaseIterable 
        case red, blue, green, yellow
    

    @State private var whichScreen = WhichScreen.red

    var body: some View 
        VStack 
            Picker("screen", selection: $whichScreen.animation()) 
                ForEach(WhichScreen.allCases, id: \.self)  value in
                    Text(value.rawValue).tag(value)
                
            
            .pickerStyle(SegmentedPickerStyle())
            Group 
                switch whichScreen 
                case .red:
                    Color.red
                case .blue:
                    Color.blue
                case .green:
                    Color.green
                case .yellow:
                    Color.yellow
                
            
            .transition(.slide)
        
    


【讨论】:

是的,没错。在我的特定用例中,我将所有这些都放在另一个视图之上,在这种情况下,您的代码仅在使用 .transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading))) 修饰符时才能按需要工作。但这实际上是更简单的解决方案。谢谢。【参考方案2】:

要获得您正在寻找的幻灯片动画,需要将.transition 应用于您想要滑动的部分(例如,在这种情况下为非黑色):

ZStack 
    Color.black
    Group 
        switch whichScreen 
        case .red:
            Color.red
        case .blue:
            Color.blue
        case .green:
            Color.green
        case .yellow:
            Color.yellow
        
    .transition(.slide)

如果您希望它与NavigationLink 转换完全一样,您仍然需要多做一步,这就是现在,“旧”或“以前”视图在转换之前消失的事实。如果您希望将其包含在堆栈中,您可以执行以下操作:

struct ContentView: View 
    
    enum WhichScreen: String, CaseIterable 
        case red, blue, green, yellow
    
    
    @State private var whichScreen = WhichScreen.red
    @State private var previousScreen : WhichScreen? = .none
    
    var body: some View 
        VStack 
            Picker("screen", selection: $whichScreen.animation()) 
                ForEach(WhichScreen.allCases, id: \.self)  value in
                    Text(value.rawValue).tag(value)
                
            
            .pickerStyle(SegmentedPickerStyle())
            .onChange(of: whichScreen)  [whichScreen] _ in
                previousScreen = whichScreen
            
            ZStack 
                Color.black
                if let previousScreen = previousScreen 
                    switch(previousScreen) 
                    case .red:
                        Color.red
                    case .blue:
                        Color.blue
                    case .green:
                        Color.green
                    case .yellow:
                        Color.yellow
                    
                    
                
                Group 
                    switch whichScreen 
                    case .red:
                        Color.red
                    case .blue:
                        Color.blue
                    case .green:
                        Color.green
                    case .yellow:
                        Color.yellow
                    
                .transition(.slide)
            
        
    

【讨论】:

太棒了!非常感谢你!我刚刚注意到过渡在预览中不起作用。我不知道我是否可以再次信任预览版。

以上是关于SwiftUI:动画过渡的主要内容,如果未能解决你的问题,请参考以下文章

滚动视图中的 SwiftUI 动画/过渡表现奇怪

如何在 SwiftUI 中动画/过渡文本值更改

SwiftUI - 过渡动画在 GeoReader 中不起作用?

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

NavigationView中的SwiftUI自定义动画过渡?

SwiftUI 动画:一些隐式过渡动画在 iOS 13 上被破坏了?