SwiftUI:动画过渡

问题描述

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

在下面的示例代码中,我制作了一个选择器来选择要显示的视图,我的目标是拥有一个看起来类似于 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)
        }
    }
}

解决方法

要获得您正在寻找的幻灯片动画,.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)
            }
        }
    }
}
,

您是否真的需要黑色的 ZStack(在您的示例代码段中从未可见)?没有它,转换开箱即用(在模拟器中,而不是在 SwiftUI 预览中):

struct ContentView: View {

    enum WhichScreen: String,yellow
    }

    @State private var whichScreen = WhichScreen.red

    var body: some View {
        VStack {
            Picker("screen",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)
        }
    }

}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...