Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting UISplitViewController's preferredDisplayMode whilst pushing onto detail navigation

I have a standard UISplitViewController, with navigation controllers in both its master and detail panes. Most of the time, the split view controller has its preferredDisplayMode set to .allVisible so that both the master and detail are visible.

When I push a particular view controller onto the detail navigation stack, I'd like to hide the master pane so that the user has more of a 'full screen' view. To implement this, I tried changing the preferredDisplayMode to .primaryHidden in viewWillAppear of the detail view controller, and changing it back in viewWillDisappear. However, this results in a really bad animation, and incorrectly placed views at the end of the transition.

Incorrect animation

I'm unsure how to fix this. I've tried changing the display mode at different times, placing the call to change the preferredDisplayMode into an animation block (although it's implicitly animated anyway), and asking the view controller's view to lay itself back out. It looks a little better in an animation block, and the views end up correctly placed, but the animation is still kind of weird and jumpy.

So, how do fix the animation and achieve the appearance I'm looking for?

I put together a minimal sample project to demonstrate the problem. Simply click the 'Push' button in the detail view controller to present the view controller that reconfigures the split view controller.

like image 348
James Frost Avatar asked Nov 08 '22 07:11

James Frost


1 Answers

Try using prepareForSegue in the DetailViewController. This will change the .preferredDisplayStyle of your UISplitViewController before presenting FullscreenViewController, with smoother animations.

In storyboard, the select the show segue from the 'push' button to the FullscreenViewController and set it's identifier (I always use the name of the destination ViewController.) Then in DetailViewController:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "FullscreenViewController" {
        self.splitViewController?.preferredDisplayMode = .primaryHidden
    }
}

For a quick fix when navigating 'back' to DetailViewController, I added

self.splitViewController?.preferredDisplayMode = .allVisible

to viewWillAppear in DetailViewController. I typically use a delegate to pass data between view controllers, and set the display mode there. Hope that helps.

like image 61
Jeremy Moore Avatar answered Nov 14 '22 21:11

Jeremy Moore