Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hiding UISplitViewController overlay in portrait

In adopting the new UISplitViewController I'm trying to make a change a default behaviour that occurs when using the UISplitViewControllerDisplayModeAutomatic mode.

When working in portrait I want the primary overlay to hide when the user triggers a push to the detail side. By default the overlay remains onscreen until the user taps over on the detail side.

I've tried using the following with the delegate:

- (BOOL)splitViewController:(UISplitViewController *)splitViewController showDetailViewController:(UIViewController *)vc sender:(id)sender
{
    if (splitViewController.displayMode == UISplitViewControllerDisplayModePrimaryOverlay) {
        [UIView animateWithDuration:0.3 animations:^{
            splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
        }];
    }
    return NO;
}

This gives me the desired behavior in portrait, but this breaks landscape mode (which I want to behave like UISplitViewControllerDisplayModeAllVisible). If you've done a push and then rotate the device the left side is still hidden (as expected). I can't find an appriprite place to hook in to re-set the prefered mode on rotation to show the left side (since trait collections can't be used to tell landscape vs portrait on the iPad).

How can I manually trigger a dismissal of the overlay?

Dupe note: iOS8 has changed UISplitViewController entirely, so all other SO answers before June '14 are probably wrong (and I've dug through many of them, just incase)

like image 428
Parrots Avatar asked Aug 28 '14 20:08

Parrots


3 Answers

I was having the same problem as you. I am doing this on Xamarin's mono touch platform, but I would think the result would be the same.

Like what LaborEtArs said, move your code to the prepareForSegue:sender: method of the master view controller. Then just set the mode to automatic after you set it to hidden:

if (splitViewController.displayMode == UISplitViewControllerDisplayModePrimaryOverlay) {
    splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
    splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic;
}

After doing it this way, it's no longer breaking landscape mode.

like image 61
Cory Juhlin Avatar answered Oct 20 '22 12:10

Cory Juhlin


Just place your code (without the return NO;) in the master view controllers prepareForSegue:sender: or tableView:didSelectRowAtIndexPath: method. There it works perfectly!

like image 29
LaborEtArs Avatar answered Oct 20 '22 12:10

LaborEtArs


In addition to the advice from LaborEtArs to do your animation in prepareForSegue:sender: or tableView:didSelectRowAtIndexPath:, if your app normally has splitViewController:preferredDisplayMode set to UISplitViewControllerDisplayModeAutomatic, simply use the animateWithDuration: method with a completion handler to restore the displayMode after the animation:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([[segue identifier] isEqualToString:@"showDetail"]) {

        // configure the detail controller

        if (self.splitViewController.displayMode == UISplitViewControllerDisplayModePrimaryOverlay) {
            [UIView animateWithDuration:0.3 animations:^{
                self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
            } completion:^(BOOL finished){
                self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic;
        }];
    }
}
like image 2
JBJr Avatar answered Oct 20 '22 11:10

JBJr