Hiding/showing status bar makes navigation bar jump down

86 views Asked by At

I have a UIViewController (CameraViewController) and a UINavigationController (ListsNavController). They are embedded inside another view controller, MasterViewController, like this:

class MasterViewController {
    /// I also have `removeFromParent` and other cleanup, but I don't think it's relevant to my question...
    func embedCamera() { 
        self.addChild(cameraViewController)
        view.insertSubview(cameraViewController.view, at: 0)
            
        cameraViewController.view.frame = view.bounds
        cameraViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
            
        cameraViewController.view.layoutIfNeeded()
    }
    func embedLists() {
        self.addChild(listsNavController)
        view.addSubview(newViewController.view)
            
        listsNavController.view.frame = view.bounds
        listsNavController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
            
        listsNavController.view.layoutIfNeeded()
    }
}

This all works fine. However, I want to hide the status bar when CameraViewController is active, but show it when listsNavController is active. I'm doing it like this:

enum ViewControllerType {
    case camera
    case lists
}

class MasterViewController {
    var currentViewControllerType = ViewControllerType.camera
    override var prefersStatusBarHidden: Bool {
        if currentViewControllerType == .camera {
            return true
        } else {
            return false
        }
    }

    func goToLists() {
        listsNavController.view.frame.origin.x = view.frame.width
        UIView.animate(withDuration: 1, animations: {
            self.listsNavController.view.frame.origin.x -= self.view.frame.width
        }) { _ in

            /// on completion, I show the status bar
            self.currentViewControllerType = .lists
            self.setNeedsStatusBarAppearanceUpdate()
            
            self.listsNavController.didMove(toParent: self)
        }
    }
    func goToCamera() {
        /// I hide the status bar just before starting the animation
        self.currentViewControllerType = .camera
        self.setNeedsStatusBarAppearanceUpdate()
        
        listsNavController.view.frame.origin.x = 0
        UIView.animate(withDuration: 1, animations: {
            self.listsNavController.view.frame.origin.x += self.view.frame.width
        }) { _ in
            self.cameraViewController.didMove(toParent: self)
        }
    }
}

And this is what it looks like (going from cameraViewController to listsNavController and back):

going from "camera View Controller" to "lists Nav Controller" and back

The problem is that, when I show the status bar, the navigation bar and everything underneath it jumps down. (To keep the gif small I didn't show what's underneath the bar, but everything jumps.) Also, when I come back (from listsNavController to cameraViewController), the navigation bar's title animates, but everything underneath still jumps.

Is there a way to animate that jump so that it's smooth? Or preferably, have no jump at all (Have some sort of "placeholder" above the navigation bar when the status bar is hidden")?

Thanks in advance. I can provide more code if needed.

0

There are 0 answers