基于MVVM+C模式修改UINavigationBar返回按钮的问题求助
问题根因
- 错误赋值
backBarButtonItem:该属性作用于当前控制器push出的下一级页面的返回按钮,给导航控制器本身的navigationItem设置完全无效,需要在全局外观中统一配置 - iOS13+ 外观优先级问题:使用
UINavigationBarAppearance配置导航栏样式后,单独修改UINavigationBar的backIndicatorImage等属性会被更高优先级的appearance配置覆盖,必须把返回按钮相关配置也写入appearance - 导航栏显隐切换导致样式重置:在
viewWillAppear/viewWillDisappear中切换导航栏显隐时,部分系统版本会重置导航栏样式,需要确保样式配置为全局生效
修复代码
将AppDelegate中导航栏初始化代码替换为以下内容即可:
let navigationController: UINavigationController = .init() // 如果需要保留自定义图片的原色,将.alwaysTemplate改为.alwaysOriginal let backButtonImage = UIImage(named: "backButton")?.withRenderingMode(.alwaysTemplate) if #available(iOS 13.0, *) { let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = .backgroundColor appearance.shadowColor = nil appearance.shadowImage = nil // 配置返回按钮自定义图片 appearance.setBackIndicatorImage(backButtonImage, transitionMaskImage: backButtonImage) // 隐藏返回按钮文字:将文字偏移到屏幕可视范围外 appearance.backButtonAppearance.normal.titlePositionAdjustment = UIOffset(horizontal: -1000, vertical: 0) navigationController.navigationBar.standardAppearance = appearance navigationController.navigationBar.scrollEdgeAppearance = appearance // 适配横竖屏切换场景 navigationController.navigationBar.compactAppearance = appearance } else { navigationController.navigationBar.isTranslucent = false navigationController.navigationBar.barTintColor = .backgroundColor navigationController.navigationBar.shadowImage = nil navigationController.navigationBar.shadowColor = nil // iOS13以下版本配置返回按钮 navigationController.navigationBar.backIndicatorImage = backButtonImage navigationController.navigationBar.backIndicatorTransitionMaskImage = backButtonImage // 全局隐藏返回按钮文字 UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffset(horizontal: -1000, vertical: 0), for: .default) } navigationController.navigationBar.tintColor = .primary window?.rootViewController = navigationController window?.makeKeyAndVisible()
侧滑返回失效修复
如果修改后出现侧滑返回功能失效的问题,添加以下扩展即可恢复:
extension UINavigationController: UIGestureRecognizerDelegate { override open func viewDidLoad() { super.viewDidLoad() interactivePopGestureRecognizer?.delegate = self } public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { return viewControllers.count > 1 } }
内容的提问来源于stack exchange,提问作者Peter Hlavatík
相关产品推荐
相关产品推荐

