Как отключить анимацию push и pop в NavigationView

Учитывая это просто NavigationView:

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

Кто-нибудь нашел способ отключить NavigationView анимация, когда представление цели помещается в стек?

Это стало возможным в UIKit начиная с iOS2.0! Я думаю, что это не так уж много, чтобы просить от структуры. Я попробовал все виды модификаторов на всех видах (то есть, NavigationView контейнер, вид назначения, NavigationLink, и т.д)

Вот некоторые из модификаторов, которые я пробовал:

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

Никто не имел значения. Я не нашел ничего полезного в EnvironmentValues или:-(

Я что-то упускаю очень очевидное, или функциональности просто еще нет?

4 ответа

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"))
            }
        }
    }
}

Сначала вам нужно состояние для 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
                    }
                }
            }
        }
    }
}

Недавно я создал проект с открытым исходным кодом под названием 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")
            }
        }
    }
}

PushView а также PopView это два представления, которые позволяют нажимать и открывать представления (аналогично 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()
    }
}

Результат:

Было бы здорово, если бы вы, ребята, присоединились ко мне в улучшении этого проекта с открытым исходным кодом.

Начиная с iOS и iPadOS 16.2, вы можете отключить анимациюNavigationStack, как указано в примечаниях к выпуску iOS и iPadOS 16.2 .

В следующем примере показана возможная реализация программного отключения анимации приViewнажимается или выталкивается:

      enum Destination {
    case details
}
      import SwiftUI

struct ContentView: View {
    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            Form {
                NavigationLink(value: Destination.details) {
                    Text("Push (with animation)")
                }
                Button("Push (no animation)") {
                    var transaction = Transaction()
                    transaction.disablesAnimations = true
                    withTransaction(transaction) {
                        path.append(Destination.details)
                    }
                }
            }
            .navigationDestination(for: Destination.self) { destination in
                switch destination {
                case .details:
                    DetailsView(path: $path)
                }
            }
        }
    }
}
      import SwiftUI

struct DetailsView: View {
    @Binding var path: NavigationPath

    var body: some View {
        Button("Pop (no animation)") {
            var transaction = Transaction()
            transaction.disablesAnimations = true
            withTransaction(transaction) {
                path.removeLast()
            }
        }
    }
}
Другие вопросы по тегам