如何禁用 NavigationView 推送和弹出动画

How to disable NavigationView push and pop animations

鉴于这个简单 NavigationView:

struct ContentView : View {
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink("Push Me", destination: Text("PUSHED VIEW"))
            }
        }
    }
}

有没有人找到当目标视图是 pushed/popped into/from 堆栈时禁用 NavigationView 动画的方法?

自 iOS2.0 以来,这在 UIKit 中已成为可能!我觉得从框架上要求也不过分。我在所有视图上尝试了各种修饰符(即 NavigationView 容器、目标视图、NavigationLink 等)

这些是我尝试过的一些修饰符:

.animation(nil)
.transition(.identity)
.transaction { t in t.disablesAnimations = true }
.transaction { t in t.animation = nil }

None 有所作为。我也没有在 EnvironmentValues 中找到任何有用的东西:-(

我是不是遗漏了一些非常明显的东西,或者功能还不存在?

Xcode 11.3:

目前没有禁用 NavigationView 动画的修改器。

您可以使用结构 init() 来禁用动画,如下所示:

struct ContentView : View {

    init(){
        UINavigationBar.setAnimationsEnabled(false)
    }

    var body: some View {
        NavigationView {
            VStack {
                NavigationLink("Push Me", destination: Text("PUSHED VIEW"))
            }
        }
    }
}

我最近创建了一个名为 swiftui-navigation-stack (https://github.com/biobeats/swiftui-navigation-stack) 的开源项目,其中包含 NavigationStackView,一个模仿标准 NavigationView 添加的导航行为的视图一些有用的功能。例如,您可以使用 NavigationStackView 并按照问题中 Kontiki 的要求禁用过渡动画。创建 NavigationStackView 时,只需将 .none 指定为 transitionType:

struct ContentView : View {
    var body: some View {
        NavigationStackView(transitionType: .none) {
            ZStack {
                Color.yellow.edgesIgnoringSafeArea(.all)

                PushView(destination: View2()) {
                    Text("PUSH")
                }
            }
        }
    }
}

struct View2: View {
    var body: some View {
        ZStack {
            Color.green.edgesIgnoringSafeArea(.all)
            PopView {
                Text("POP")
            }
        }
    }
}

PushViewPopView 是允许您推送和弹出视图的两个视图(类似于 SwiftUI NavigationLink)。这是完整的例子:

import SwiftUI
import NavigationStack

struct ContentView : View {
    var body: some View {
        NavigationStackView(transitionType: .none) {
            ZStack {
                Color.yellow.edgesIgnoringSafeArea(.all)

                PushView(destination: View2()) {
                    Text("PUSH")
                }
            }
        }
    }
}

struct View2: View {
    var body: some View {
        ZStack {
            Color.green.edgesIgnoringSafeArea(.all)
            PopView {
                Text("POP")
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

结果是:

如果你们能和我一起改进这个开源项目,那就太好了。

首先您需要 NavigationLink 响应的状态,然后在禁用动画的事务中设置该状态,如下所示:

struct ContentView : View {
    @State var isActive = false
    
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(isActive: $isActive, destination: {
                    Text("PUSHED VIEW")}) {
                    Text("Push Me")
                }
                Button("Navigate Without Animation") {
                    var transaction = Transaction()
                    transaction.disablesAnimations = true
                    withTransaction(transaction) {
                        isActive = true
                    }
                }
            }
        }
    }
}