I have a UIPageViewController
subclass that allows the user to swipe upward from the initial view controller to a second view controller. The initial view controller does not have a navigation bar (it's not connected to a UINavigationController
), but the second one does. Currently, when I swipe up to present the second view controller, there is no space in the navigation bar for the status bar. When the transition is complete, the entire view controller layout updates instantly to add the status bar space. I want to make the second view controller anticipate that the status bar will be there and add the space for it so the view doesn't jolt after the transition.
Short video clip showing the jolt
Similar, but unanswered question
EDIT:
After closely looking at the way the view controller behaves during the transition, I was able to get a good look at what is going on here.
I found a workaround that seems to work pretty well. I need to test this with the iPhone X to see if I need to make adjustments. If someone finds a better solution, I'll make it the accepted answer.
I basically shift my page view controller down by 20pt when it is loaded:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let f = view.frame
view.frame = CGRect(x: 0, y: 20, width: f.size.width, height: f.size.height)
view.setNeedsLayout()
view.layoutIfNeeded()
}
After the transition, I shift the page view controller back up to its original position at exactly the same time that the second view controller adds status bar space. This causes the second view controller to slide right below the status bar, where it should be. There's no noticeable jolt. I used this in my page view controller's delegate:
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
guard previousViewControllers.count > 0 else { return }
// if the transition completed and the view controller we transitioned from is the first view controller
if completed && viewControllers!.index(of: previousViewControllers.first!) == 0 {
let f = view.frame
view.frame = CGRect(x: 0, y: 0, width: f.size.width, height: f.size.height)
view.setNeedsLayout()
view.layoutIfNeeded()
}
}