繁体   English   中英

导航栏在更改为内联之前作为大标题短暂闪烁

[英]Navigation bar briefly flickering as large title before changing to inline

我在我的 SwiftUI 应用程序中使用了 UITabController,它运行良好,除了一个问题。

当我有一个使用大标题的 NavigationView 时,它会在我滚动时变为内联,正如预期的那样。 到目前为止,一切都很好。

当我切换标签,然后再次切换回来时,它应该记住滚动 position 并且因此是内联的。 相反,它在移动到内联之前非常短暂地闪烁为一个大标题。

这似乎只发生在设备上。

问题的屏幕记录

有人可以帮助我解决问题吗?

struct ContentView: View {
    var body: some View {
        CustomTabView([
            Tab(view: FirstView(),
                barItem: UITabBarItem(title: "First", image: UIImage(systemName: "1.circle"), selectedImage: nil)),
            Tab(view: SecondView(),
                barItem: UITabBarItem(title: "Second", image: UIImage(systemName: "2.circle"), selectedImage: nil))
        ])
    }
}

struct FirstView: View {
    var body: some View {
        NavigationView {
            List {
                ForEach( 0...40, id: \.self ) {
                    Text("\($0)")
                        .padding()
                }
            }
            .navigationTitle("First View")
        }
    }
}

struct SecondView: View {
    var body: some View {
        NavigationView {
            List {
                ForEach( 41...80, id: \.self ) {
                    Text("\($0)")
                        .padding()
                }
            }
            .navigationTitle("Second View")
        }
    }
}

struct TabBarController: UIViewControllerRepresentable {
    var controllers: [UIViewController]

    func makeUIViewController(context: Context) -> UITabBarController {
        let tabBarController = UITabBarController()
        tabBarController.viewControllers = controllers
        tabBarController.delegate = context.coordinator
        return tabBarController
    }

    func updateUIViewController(_ uiViewController: UITabBarController, context: Context) {}
    
    func makeCoordinator() -> Coordinator {
        Coordinator()
    }
    
    class Coordinator: NSObject, UITabBarControllerDelegate {
        func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
            guard let fromView = tabBarController.selectedViewController?.view, let toView = viewController.view else {
                return false
            }
            if fromView != toView {
                fromView.superview!.addSubview(toView)
            }
            return true
        }
    }
}

struct CustomTabView: View {
    var viewControllers: [UIHostingController<AnyView>]

    init(_ tabs: [Tab]) {
        self.viewControllers = tabs.map {
            let host = UIHostingController(rootView: $0.view)
            host.tabBarItem = $0.barItem
            return host
        }
    }

    var body: some View {
        TabBarController(controllers: viewControllers)
            .edgesIgnoringSafeArea(.all)
    }
}

struct Tab {
    var view: AnyView
    var barItem: UITabBarItem

    init<V: View>(view: V, barItem: UITabBarItem) {
        self.view = AnyView(view)
        self.barItem = barItem
    }
}

我找到了解决方法/修复。

我需要使用自定义 UIHostingController,找到导航 controller,并在 viewWillAppear function 中添加一行:

public class MyHostingController: UIHostingController<AnyView> {
    override open func viewWillAppear(_ animated: Bool) {
        if let navigationController = navigationController() {
            navigationController.view.setNeedsUpdateConstraints()
        }
        super.viewWillAppear(animated)
    }
}

private extension UIViewController {
    func navigationController() -> UINavigationController? {
        var controller: UINavigationController?
        
        if let navigationController = self as? UINavigationController {
            return navigationController
        }
        
        children.forEach {
            if let navigationController = $0 as? UINavigationController {
                controller = navigationController
            } else {
                controller = $0.navigationController()
            }
        }
        
        return controller
    }
}

然后显然用 MyHostingController 替换了我原始代码中 UIHostingController 的两种用法。

最重要的一行是:

navigationController.view.setNeedsUpdateConstraints()

希望这可以帮助其他发现类似问题的人。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM