如何Push新ViewController时保持NavigationItem标题不变且无切换动画?
我来帮你搞定这个需求!要让vc2的标题和vc1完全一致,同时在推送过程中不出现标题切换的动画,这里有两个实用的方案:
方案一:自定义导航栏标题视图(推荐)
系统默认的导航栏标题在控制器切换时,即使内容相同也可能触发过渡动画。通过自定义titleView,让两个控制器使用完全一致的标题视图,就能避免这个问题:
- 在vc1中配置自定义标题视图(可以放在
viewDidLoad里):
override func viewDidLoad() { super.viewDidLoad() self.title = "xxx" // 创建自定义标题标签 let titleLabel = UILabel() titleLabel.text = self.title titleLabel.font = UIFont.systemFont(ofSize: 17, weight: .semibold) titleLabel.textColor = .label // 适配明暗模式 self.navigationItem.titleView = titleLabel }
- 推送vc2时,给它配置相同的标题视图:
func pushToVC2() { let vc2 = MyViewController() // 复用和vc1一致的标题视图配置 let titleLabel = UILabel() titleLabel.text = self.title titleLabel.font = UIFont.systemFont(ofSize: 17, weight: .semibold) titleLabel.textColor = .label vc2.navigationItem.titleView = titleLabel navigationController?.pushViewController(vc2, animated: true) }
这个方案的好处是不会影响其他动画效果,稳定性更高,还能灵活定制标题的样式。
方案二:临时禁用导航栏动画
如果不想自定义标题视图,可以通过临时关闭UI动画的方式,只禁用标题的切换动画,同时保留页面推送的动画:
- 让vc1遵守
UINavigationControllerDelegate,并设置代理:
class VC1: UIViewController, UINavigationControllerDelegate { override func viewDidLoad() { super.viewDidLoad() self.title = "xxx" navigationController?.delegate = self }
- 推送vc2时临时关闭动画,在推送完成后恢复:
func pushToVC2() { let vc2 = MyViewController() vc2.title = self.title // 同步标题 // 临时关闭UI动画 UIView.setAnimationsEnabled(false) navigationController?.pushViewController(vc2, animated: true) } // 推送完成后恢复动画 func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) { UIView.setAnimationsEnabled(true) }
这个方法更简洁,但要注意必须在推送完成后恢复动画,否则会影响后续的其他UI动画效果。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

