禁用液态玻璃UI 的key 如果是27版本构建 会自动忽略
Apple Developer Documentation
自定义的Tabbar 通过 [self setValue:customTabBar forKey:@"tabBar"];设置的 也会失效或者出现各种问题
iOS 26 的 TabBar 是悬浮式设计,页面侧滑返回时,如果 TabBar 的显示状态与导航栈不一致,就可能出现 TabBar 提前显示、位置跳动或动画不协调的问题。 这需要结合 UITabBarController 和 UINavigationController 的层级来处理.
目前大多主流的层级是
1 2 3 4 5 6 7 8 9 10 11
| UITabBarController ├── BaseNavigationController(首页导航栈) │ └── HomeViewController(首页) │ └── DetailViewController(详情) │ ├── BaseNavigationController(商城导航栈) │ └── MallViewController(商城) │ └── DetailViewController(详情) │ └── BaseNavigationController(我的导航栈) └── MineViewController(我的)
|
这种 系统的Tabbar
如果是 push时不隐藏 没有问题
如果是 push时隐藏 hidesBottomBarWhenPushed = true 在侧滑的时候会提前出现 停止侧滑 又会隐藏
网上有几种方案处理:
方案一:自定义导航控制器转场代理
通过实现UINavigationControllerDelegate手动控制转场过程中的TabBar层级:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| class CustomNavigationController: UINavigationController, UINavigationControllerDelegate { override func viewDidLoad() { super.viewDidLoad() delegate = self }
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { if operation == .pop { return CustomPopTransition() } return nil } }
class CustomPopTransition: NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.35 }
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let fromVC = transitionContext.viewController(forKey: .from), let toVC = transitionContext.viewController(forKey: .to) else { transitionContext.completeTransition(false) return } let containerView = transitionContext.containerView containerView.addSubview(toVC.view) containerView.sendSubviewToBack(toVC.view) fromVC.view.frame = containerView.bounds let finalFrame = CGRect(x: containerView.bounds.width, y: 0, width: containerView.bounds.width, height: containerView.bounds.height) UIView.animate(withDuration: transitionDuration(using: transitionContext)) { fromVC.view.frame = finalFrame if let tabBar = (toVC as? UITabBarController)?.tabBar { containerView.sendSubviewToBack(tabBar) } } _ in fromVC.view.removeFromSuperview() transitionContext.completeTransition(!transitionContext.transitionWasCancelled) } } }
|
方案二:监听侧滑手势动态调整TabBar层级
在详情页监听导航控制器的侧滑手势,根据手势状态调整TabBar层级:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class DetailViewController: UIViewController { private var tabBar: UITabBar? override func viewDidLoad() { super.viewDidLoad() tabBar = tabBarController?.tabBar if let popGesture = navigationController?.interactivePopGestureRecognizer { popGesture.addTarget(self, action: #selector(handlePopGesture(_:))) } } @objc private func handlePopGesture(_ gesture: UIPanGestureRecognizer) { guard let tabBar = tabBar else { return } switch gesture.state { case .began, .changed: tabBar.superview?.sendSubviewToBack(tabBar) case .cancelled: tabBar.superview?.bringSubviewToFront(tabBar) default: break } } }
|
方案三:修改TabBar的zPosition(简洁版)
在详情页生命周期方法中直接调整TabBar的层级:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class DetailViewController: UIViewController { private var originalZPosition: CGFloat = 0 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if let tabBar = tabBarController?.tabBar { originalZPosition = tabBar.layer.zPosition tabBar.layer.zPosition = -1000 } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) if let tabBar = tabBarController?.tabBar { tabBar.layer.zPosition = originalZPosition } } }
|
方案四:修改Tabbar的层级(推荐)
TabBarController外面包一层UINavigationController 所有跳转 统一处理 比如 TheRouter 仓库
TheRouter 官网
1 2 3 4 5 6 7 8 9 10 11 12
| UINavigationController └─ UITabBarController ├── BaseNavigationController(首页导航栈) │ └── HomeViewController(首页) │ └── DetailViewController(详情) │ ├── BaseNavigationController(商城导航栈) │ └── MallViewController(商城) │ └── DetailViewController(详情) │ └── BaseNavigationController(我的导航栈) └── MineViewController(我的)
|
并禁止相关属性 设置为window.rootViewController
1 2 3 4 5 6 7 8
| nav.navigationBarHidden = YES;
nav.interactivePopGestureRecognizer.enabled = NO;
nav.interactivePopGestureRecognizer.delegate = nil;
window.rootViewController = nav;
|
注意
跳转子页面 走路由统一跳转 不能直接navigationController.pushViewController 去跳转 不然会失效