为什么在新的iOS 16 SwiftUI NavigationPath中清除“pop to root”不会平滑动画返回到根视图?

23

我有一个使用 NavigationDestination 修饰符确定导航的新 iOS 16 SwiftUI NavigationStack,它运行良好。

我的问题是:为什么在清除 NavigationPath 时,在堆栈中深度超过一个视图时,它不能通过平滑地向后滑动到根视图来进行动画处理?

如果您只有一层,则可以正常工作,但是如果比这更低,则称为“跳转到根”的操作只会跳回根视图,而不会有滑动动画。

这是“特性”还是错误或我做错了什么?

重现问题的步骤

  • 运行下面的示例代码。
  • 单击第一个导航链接,然后单击“Pop To Root View” - 注意,它会平稳地滑回根视图。
  • 单击第一个或第二个链接 - 然后单击“导航到视图3”,它会显示视图3。
  • 然后单击“弹出到根”,您会注意到它会跳回根视图,而不是滑回来。 这就是我的问题-它应该跳回还是滑回来?

问题演示

enter image description here

演示代码(使用 Xcode 14.0 和 iOS 16.0):

import SwiftUI
struct DemoPop: View {

    @State private var path = NavigationPath()
    
    var body: some View {
        
        VStack {
            
            NavigationStack(path: $path) {
                   
                List {
                    Section("List One") {
                        NavigationLink("Navigate to View 1", value: "View 1")
                        NavigationLink("Navigate to View 2", value: "View 2")
                    }
                }
                .navigationDestination(for: String.self) { textDesc in
                    
                    VStack {
                        Text(textDesc).padding()
                        Button("Navigate to View 3") {
                            path.append("View 3")
                        }.padding()
                        
                        Button("Pop to Root View") {
                            path.removeLast(path.count)
                        }.padding()
                    }
                }
                .navigationTitle("Test Pop To Root")
            }
        }
    }
}
    

struct DemoPop_Previews: PreviewProvider {
    static var previews: some View {
        DemoPop()
    }
}

更新1:

认为上述代码正确,因此可能是评论中提到的一个错误,因为我刚刚看到了一个YouTube视频,展示了相同的行为 - Youtube教程 - 在时间线19:25左右 - 您将看到弹出到根目录只会跳回起点。

更新2:

iOS 16.2中已经修复了这个问题。


我在我的测试代码中看到了相同的行为。一级深度弹出到根目录的动画完美地执行。但是,如果再深入一层,它就会直接跳回去,没有任何动画效果。我的初步想法是这肯定是个bug,但你会认为在发布之前已经有很多人测试过了,所以也许是我们做错了什么。 - kittonian
我认为这个问题可能是一个特性,因为我刚刚看到了一个展示相同功能的YouTube视频 - https://youtu.be/pwP3_OX2G9A - 在时间轴19:25左右 - 你会看到弹出到根节点只是跳回到开始。 - Mgwd
4
绝对不是一个功能。我已经向苹果提交了错误报告。 - kittonian
@kittonian 很好,我希望这只是一个漏洞,因为跳回去的感觉不太对。感谢您的评论。 - Mgwd
2个回答

5

很可能是一个bug,请向苹果提交反馈。

话虽如此,如果您使用的是iOS设备,您可以通过以下hack方法解决:

    import UIKit
    let animation = CATransition()
    animation.isRemovedOnCompletion = true
    animation.type = .moveIn
    animation.subtype = .fromLeft
    animation.duration = 0.3
    animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
    UIApplication.shared.keyWindow!.layer.add(animation, forKey: nil)
    self.navigationPath.removeLast()

这将使整个窗口,包括工具栏、选项卡栏等动起来。 - Martin
1
确实。如果没有任何技巧(将特殊视图注入层次结构),很难找到给定的SwiftUI视图对应的UIKIt视图 - 所以这里是一个妥协,直到苹果公司希望修复这个错误。 - DrMickeyLauer

4
这个问题已经被苹果在iOS 16.2中修复了。
对于iOS 16.0和16.1,这里有一个100%有效的一行代码解决方案。将此SPM库添加到您的代码库https://github.com/davdroman/swiftui-navigation-transitions(版本0.7.1或更高),然后简单地执行以下操作:
import NavigationTransitions
import SwiftUI

struct DemoPop: View {

    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            List {
                Section("List One") {
                    NavigationLink("Navigate to View 1", value: "View 1")
                    NavigationLink("Navigate to View 2", value: "View 2")
                }
            }
            .navigationDestination(for: String.self) { textDesc in

                VStack {
                    Text(textDesc).padding()
                    Button("Navigate to View 3") {
                        path.append("View 3")
                    }.padding()

                    Button("Pop to Root View") {
                        path.removeLast(path.count)
                    }.padding()
                }
            }
            .navigationTitle("Test Pop To Root")
        }
        .navigationTransition(.default) // one-liner ✨
    }
}


struct DemoPop_Previews: PreviewProvider {
    static var previews: some View {
        DemoPop()
    }
}

谢谢,我可以确认你所说的,ios16.2已经解决了这个问题。 - Mgwd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接