iOS开发:从子ViewController返回根VC时平滑缩小Large UINavigationBar
Hey there! Let's fix that seamless transition you're aiming for—getting the large navigation bar in your child view controller to smoothly shrink back to the default size when returning to the root VC, just like the App Store does. I see you don't want to fully remove the large bar capability from the parent, so we'll adjust how you're handling the large title settings to leverage iOS's built-in animation.
The Issue with Your Current Setup
Right now, your disableLargeNavigationTitle function turns off the navigation bar's global prefersLargeTitles flag directly. This causes an abrupt jump instead of a smooth transition, because you're overriding the navigation controller's default behavior for animating between different title modes.
The Fix: Use Per-VC Title Display Modes
iOS 11+ handles smooth large title transitions automatically if you let it—instead of toggling the global prefersLargeTitles setting, you control each view controller's navigationItem.largeTitleDisplayMode. Here's how to adjust your code:
1. Update the enableLargeNavigationTitle Function
Keep the global prefersLargeTitles enabled on the navigation bar, and set the child VC's display mode to force large titles:
func enableLargeNavigationTitle(title: String) { self.navigationController?.view.backgroundColor = VVUtility.splashBackGroundColor() self.navigationItem.title = "\(title)".localized() self.navigationController?.navigationBar.titleTextAttributes = [ NSAttributedString.Key.foregroundColor : UIColor.white, NSAttributedString.Key.font : VVUtility.normalFontWithPlusSize(increaseSize: -2.0) ] if #available(iOS 11.0, *) { self.navigationController?.navigationBar.isTranslucent = false // Keep global large title support enabled self.navigationController?.navigationBar.prefersLargeTitles = true self.navigationController?.navigationBar.backgroundColor = VVUtility.splashBackGroundColor() self.navigationController?.navigationBar.largeTitleTextAttributes = [ NSAttributedString.Key.foregroundColor : UIColor.white, NSAttributedString.Key.font : VVUtility.normalFontWithPlusSize(increaseSize: 0.0) ] // Force this VC to show large titles self.navigationItem.largeTitleDisplayMode = .always } else { // Fallback on earlier versions } }
2. Rewrite the disableLargeNavigationTitle Function
Instead of disabling global large titles, just tell the parent VC to never show them:
func disableLargeNavigationTitle() { if #available(iOS 11.0, *) { // Only disable large titles for THIS view controller self.navigationItem.largeTitleDisplayMode = .never } else { // Fallback on earlier versions } }
3. Clean Up Your View Controller Code
- Child View Controller: Remove any unnecessary overrides that might interfere with transitions. Keep it simple:
override func viewDidLoad() { super.viewDidLoad() self.initUI() super.enableLargeNavigationTitle(title: (self.favorty?.sellerProduct?.product?.name)!) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) super.removeTitleImage() } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) }
- Parent View Controller: Avoid redundant calls to
disableLargeNavigationTitle—one call inviewDidLoadis enough. The navigation controller will handle the animation automatically when you return:
override func viewDidLoad() { super.viewDidLoad() self.initUI() self.getData() super.disableLargeNavigationTitle() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.navigationController?.navigationBar.addSubview(searchBarBoxView) self.timerDelegate?.startTimer() self.navigationController?.setNavigationBarHidden(false, animated: true) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) self.searchBarBoxView.removeFromSuperview() self.timerDelegate?.stopTimer() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) self.tabBarController?.delegate = self }
Why This Works
By keeping the navigation controller's prefersLargeTitles set to true globally, you let iOS manage the transition animation between the child VC's .always large title mode and the parent VC's .never mode. This gives you that smooth, gradient shrink effect just like the App Store uses—no extra animation code needed!
内容的提问来源于stack exchange,提问作者Omid Kia

