如何在TabBarController下仅隐藏两个ViewController的NavigationBar
修复TabBarController切换时导航栏异常显示的问题
问题根源:当两个需要隐藏导航栏的ViewController(timerView和rankingView)之间切换时,前一个VC的viewWillDisappear会先将导航栏设为显示,而后一个VC的viewWillAppear才会将其隐藏,中间的状态切换导致导航栏短暂显示。
以下两种方案可解决该问题:
方案一:修改单个VC的消失逻辑
在TimerViewController和RankingViewController中,仅当即将切换到需要显示导航栏的TeamViewController时,才恢复导航栏显示:
override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 判断即将显示的VC是否为需要显示导航栏的类型 guard let tabBarVC = tabBarController, let nextVC = tabBarVC.selectedViewController else { return } // 只有切换到TeamViewController时才恢复导航栏 if nextVC is TeamViewController { navigationController?.setNavigationBarHidden(false, animated: animated) } }
保留原有的viewWillAppear代码不变:
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.setNavigationBarHidden(true, animated: animated) }
方案二:在TabBarController中统一控制导航栏状态(推荐)
将导航栏的显示逻辑集中到PlayerTabBarController中,避免多个VC各自处理导致的冲突:
- 修改
PlayerTabBarController代码,让其遵守UITabBarControllerDelegate并统一管理导航栏状态:
class PlayerTabBarController: UITabBarController, UITabBarControllerDelegate { override func viewDidLoad() { super.viewDidLoad() configureNavBar() self.delegate = self // 设置代理 } func configureNavBar() { let backButton = UIButton(frame: CGRect(x: 0, y: 0, width: 20, height: 10)) backButton.setImage(UIImage(named: "leave 1"), for: .normal) backButton.addTarget(self, action: #selector(onBackPressed), for: .touchUpInside) let barBackButton = UIBarButtonItem(customView: backButton) self.navigationItem.leftBarButtonItem = barBackButton } @objc func onBackPressed() { self.navigationController?.popViewController(animated: true) } // Tab切换时更新导航栏状态 func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { let shouldHide = viewController is TimerViewController || viewController is RankingViewController navigationController?.setNavigationBarHidden(shouldHide, animated: true) } // 初始加载时设置正确的导航栏状态 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) guard let selectedVC = selectedViewController else { return } let shouldHide = selectedVC is TimerViewController || selectedVC is RankingViewController navigationController?.setNavigationBarHidden(shouldHide, animated: false) } }
- 删除
TimerViewController和RankingViewController中所有关于setNavigationBarHidden的代码,避免重复处理。
内容的提问来源于stack exchange,提问作者nakim81
相关产品推荐
相关产品推荐

