Home uses a custom top bar, so TabNavigationController now syncs system nav bar visibility with the stack top; remove the scan tab text label to show icon only. Co-authored-by: Cursor <cursoragent@cursor.com>
99 lines
4.0 KiB
Swift
99 lines
4.0 KiB
Swift
//
|
||
// TabNavigationController.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import UIKit
|
||
|
||
@MainActor
|
||
/// 单个 Tab 的 UIKit 导航栈,负责承载该 Tab 内部页面层级。
|
||
final class TabNavigationController: UINavigationController {
|
||
|
||
let appTab: AppTab
|
||
private let services: AppServices
|
||
|
||
/// 初始化实例。
|
||
init(tab: AppTab, services: AppServices) {
|
||
self.appTab = tab
|
||
self.services = services
|
||
super.init(nibName: nil, bundle: nil)
|
||
delegate = self
|
||
navigationBar.prefersLargeTitles = false
|
||
setViewControllers([tab.makeRootViewController(services: services)], animated: false)
|
||
}
|
||
|
||
@available(*, unavailable)
|
||
required init?(coder: NSCoder) {
|
||
fatalError("init(coder:) has not been implemented")
|
||
}
|
||
|
||
/// Push 指定应用路由,并统一设置底部 TabBar 隐藏策略。
|
||
func push(route: AppRoute, animated: Bool = true) {
|
||
let viewController = AppRouteViewControllerFactory.makeViewController(for: route, services: services)
|
||
viewController.hidesBottomBarWhenPushed = route.hidesTabBarWhenPushed
|
||
pushViewController(viewController, animated: animated)
|
||
}
|
||
|
||
/// Push 页面时按目标页同步系统导航栏状态,覆盖各页面直接调用系统 push 的场景。
|
||
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
|
||
updateNavigationBarVisibility(for: viewController, animated: animated)
|
||
super.pushViewController(viewController, animated: animated)
|
||
}
|
||
|
||
/// 设置导航栈时按最终栈顶同步系统导航栏状态。
|
||
override func setViewControllers(_ viewControllers: [UIViewController], animated: Bool) {
|
||
if let topViewController = viewControllers.last {
|
||
updateNavigationBarVisibility(for: topViewController, animated: animated)
|
||
}
|
||
super.setViewControllers(viewControllers, animated: animated)
|
||
}
|
||
|
||
/// 弹出页面后按新的栈顶同步系统导航栏状态。
|
||
override func popViewController(animated: Bool) -> UIViewController? {
|
||
let poppedViewController = super.popViewController(animated: animated)
|
||
if !animated, let topViewController {
|
||
updateNavigationBarVisibility(for: topViewController, animated: false)
|
||
}
|
||
return poppedViewController
|
||
}
|
||
|
||
/// 回到根页面后按根页面同步系统导航栏状态。
|
||
override func popToRootViewController(animated: Bool) -> [UIViewController]? {
|
||
let poppedViewControllers = super.popToRootViewController(animated: animated)
|
||
if !animated, let topViewController {
|
||
updateNavigationBarVisibility(for: topViewController, animated: false)
|
||
}
|
||
return poppedViewControllers
|
||
}
|
||
|
||
/// 弹到指定页面后按该页面同步系统导航栏状态。
|
||
override func popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? {
|
||
let poppedViewControllers = super.popToViewController(viewController, animated: animated)
|
||
if !animated, let topViewController {
|
||
updateNavigationBarVisibility(for: topViewController, animated: false)
|
||
}
|
||
return poppedViewControllers
|
||
}
|
||
|
||
/// 根据页面类型判断系统导航栏是否应隐藏。
|
||
private func shouldHideNavigationBar(for viewController: UIViewController) -> Bool {
|
||
viewController is HomeViewController
|
||
}
|
||
|
||
/// 将系统导航栏显示状态同步到目标页面,避免首页隐藏状态泄漏到子页面。
|
||
private func updateNavigationBarVisibility(for viewController: UIViewController, animated: Bool) {
|
||
setNavigationBarHidden(shouldHideNavigationBar(for: viewController), animated: animated)
|
||
}
|
||
}
|
||
|
||
extension TabNavigationController: UINavigationControllerDelegate {
|
||
/// 导航转场即将展示页面时更新系统导航栏显隐状态。
|
||
func navigationController(
|
||
_ navigationController: UINavigationController,
|
||
willShow viewController: UIViewController,
|
||
animated: Bool
|
||
) {
|
||
updateNavigationBarVisibility(for: viewController, animated: animated)
|
||
}
|
||
}
|