UISplitViewController适配多设备时detail页出现双重UINavigationBar问题求解
方案1:动态控制子导航栏显隐(代码量最少,适配成本最低)
监听traitCollection变化,根据当前水平尺寸类动态切换子UINavigationController的导航栏显隐状态即可:
- Objective-C实现(在
UITabBarController子类中重写方法):
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { [super traitCollectionDidChange:previousTraitCollection]; BOOL isCompact = (self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact); // 遍历所有tab下的导航控制器,统一控制导航栏显隐 for (UINavigationController *navVC in self.viewControllers) { navVC.navigationBarHidden = isCompact; } }
- Swift实现:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) let isCompact = traitCollection.horizontalSizeClass == .compact viewControllers?.compactMap { $0 as? UINavigationController }.forEach { $0.isNavigationBarHidden = isCompact } }
适配说明:
- compact环境下隐藏子导航栏,直接使用
UISplitViewController自带的导航栏,避免双层叠加 - 非compact环境下显示子导航栏,此时
UISplitViewController不会生成额外导航栏,保持原有正常布局 - 子页面自定义导航栏按钮、标题的逻辑无需大改,直接设置当前控制器的
navigationItem即可,系统会自动对应到当前活跃的导航栏上
方案2:重写SplitViewController跳转代理(从根源避免双层栈问题)
实现UISplitViewControllerDelegate协议,自定义showDetailViewController的跳转逻辑:
- (BOOL)splitViewController:(UISplitViewController *)splitViewController showDetailViewController:(UIViewController *)vc sender:(id)sender { // compact环境下自定义跳转逻辑 if (splitViewController.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) { // 取当前tab选中的子导航控制器做push,避免把整个UITabBarController压入split导航栈 UITabBarController *tabVC = (UITabBarController *)splitViewController.viewControllers.lastObject; UINavigationController *activeNav = (UINavigationController *)tabVC.selectedViewController; [activeNav pushViewController:vc animated:YES]; return YES; } // 非compact环境走系统默认逻辑 return NO; }
该方案无需修改导航栏显隐逻辑,直接从跳转行为层面规避了compact环境下生成双层导航栈的问题。
内容的提问来源于stack exchange,提问作者user14664032
相关产品推荐
相关产品推荐

