views:

273

answers:

2

I want to have a UIView take over the whole screen to display an image from time to time, but most of the time I'm using a UISplitViewController for the main app functionality. Is there a recommended/best practice way to do this? Right now, I have a pointer to the main window and am just adding the UIView as a sub view and bringing it to front, but it won't display in the proper orientation. I was just wondering if there is a better way/something simple I'm missing.

Thanks.

+1  A: 

I struggled with this same issue for some time and have come up with a clunky workaround. Before my solution, some more background on the obstacles:

  • In iPhone OS, the root view's coordinates are always in the literal fixed coordinates of the physical screen. "Up" is always device up. Subviews have to get coordinates which have been converted to a given orientation so that "Up" is what we expect to be: gravitational up.
  • Placing a UIView at the top of the view hierarchy (above the UIScrollView) would therefore require that you make these conversions yourself during orientation events. You get fullscreen, but you lose the benefit of the scrollView managing orientation coordinates for your subviews.
  • Keeping your view within the scrollView, there is no easy method as in Mac OS to simply collapse a pane of a splitView. Reviewing the header file reveals some private instance methods used to manage width.

So, I think that what you can do is maintain two "orientation-aware" view controllers (one splitView, one fullscreen), and switch them out and move your view between them when you toggle fullscreen. I did not go this route as it is obviously a touchy situation memory- and view-hierarchy- wise.

What I do is switch between an "almost fullscreen" width for the main view and regular split width. This works great except that the splitView's rounded corners are actually hard-coded images that get draw regardless of the splitView's dimensions. You will see these tiny black round corners 100% of the time. Here is the effect:

- (IBAction)toggleFullscreen:(id)sender; {
id appDelegate = [[UIApplication sharedApplication] delegate];
UISplitViewController *split = [appDelegate splitViewController];

//get master and detail view controller
UIViewController *master = [split.viewControllers objectAtIndex:0];
UIViewController *detail = [split.viewControllers objectAtIndex:1];

//In landscape permit fullscreen
if(self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
   self.interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
    CGRect f = detail.view.frame;
    if ( f.origin.x == 0 ) { //exiting fullscreen
        [sender setImage:[UIImage imageNamed:@"SlideLeft.png"]];
        //adjust detail view
            f.size.width = 703;
            f.origin.x = 321;
        [detail.view setFrame:f];

        //adjust master view
            f = master.view.frame;
            f.size.width = 320;
            f.origin.x = 0;
        [master.view setFrame:f];       

    } else { //entering fullscreen
        [sender setImage:[UIImage imageNamed:@"SlideRight.png"]];
        //adjust detail view
            f.size.width = 1024;
            f.origin.x = 0;     
        [detail.view setFrame:f];

        //adjust master view
        f = master.view.frame;
            f.size.width = 1;
            f.origin.x = -1;
        [master.view setFrame:f];
    }       
}
}

I got lots of this code from here and other sources, but as far as I know this implementation is unique. Probably because it is imperfect.

SG1
Thanks for your feedback on this. I've actually done something similar. I was just hoping that there was a simpler (less code) way to implement it. Have you looked at -setWantsFullScreenLayout on UIViewController? There seems to be something there, but when I use that something is still messed up as the view displays in portrait though I'm in landscape. It's annoying, but I'm sure I'm just doing it wrong. ;-)
Matt Long
From what I read that method affects only whether the black status bar displays or not. It's a misnomer at "wants full screen"; it should be called "shows status bar".
SG1
+1  A: 

I ended up using a modal view controller which I present from the split view controller. I then specify the allowed orientations in -shouldAutorotateToInterfaceOrientation. I also hide the status bar. This works for my needs.

Matt Long