【问题标题】:SwiftUI: Animate TransitionsSwiftUI:动画过渡
【发布时间】: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)
        }
    }
}

【问题讨论】:

    标签: swift swiftui swiftui-animation swiftui-zstack


    【解决方案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)
                }
            }
        }
    }
    

    【讨论】:

    • 太棒了!非常感谢你!我刚刚注意到过渡在预览中不起作用。我不知道我是否可以再次信任预览版。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    • 2020-03-25
    • 2020-04-03
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多