Today we have a little iPhone user interface programming problem to present to you with its not so self evident solution, courtesy of the kind assistance of one Bryan Henry on the iphonesdk list.
The scenario is, we’ve pushed a pack of controllers onto our UINavigationController as we drill down through the interface, and now we’ve reached a place where the user taps something that we want to enter a full screen display state for momentarily. Well, that’s easy enough, the naïve iPhone programmer thinks to himself, we’ll just hide the status bar then modally present a controller with a full screen view, right?
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];
FullscreenController *fullscreenController = [[FullscreenController alloc] initWithNibName:@”Fullscreen” bundle:nil];
[self.navigationController presentModalViewController:fullscreenController animated:NO];
[fullscreenController release];
Yes, he would think that. But he WOULD BE WRONG. What actually happens is that the view is presented below the empty space where the status bar used to be. Bah. Fooling with offsets in the “Fullscreen” xib file simply results in the view being clipped by that empty space. Double bah. Thankfully, a plaintive plea to the list produces in short order an explanation:
Your problem is that the UITransitionView that is used to animate in
your modal view has clipsToBounds=YES, so any drawing that should
happen in the rect where the status bar would be doesn’t happen since
the UITransitionView’s bounds don’t extend there. I ran into this just
the other day. The (somewhat hackish but completely safe) solution was
to set clipsToBounds=NO for the UITransitionView whenever its set as
the superview (or rather, whenever your view is added as a subview of
the UITransitionView).
Well, that was somewhat less than intuitive, wasn’t it now? So what you need is a patched UIView class,
@interface NoClipModalView : UIView
{
}
@end
@implementation NoClipModalView
- (void)didMoveToSuperview
{
self.superview.clipsToBounds = NO;
}
@end
and then in your controller, rather than having it actually load the nib, you override -loadView to have it create one of those, and then create your fullscreen views inside it.
- (void)loadView
{
// instead of calling [super loadView], which doesn’t account for a hidden status bar, create an unclipped view here
CGSize screenSize = [UIScreen mainScreen].bounds.size;
CGRect screenBounds = CGRectMake(0, -20, screenSize.width, screenSize.height);
NoClipModalView *sView = [[NoClipModalView alloc] initWithFrame:screenBounds];
self.view = sView;
[sView release];
// and then manually create the view(s) you want inside it.
TWGestureImageView *newImageView = [[[TWGestureImageView alloc] initWithFrame:screenBounds] autorelease];
self.imageView = newImageView;
[self.view addSubview:self.imageView];
}
And that, dear friends, is how to create a full screen modal display. Reverse it from where you created the FullscreenController up at the top with the expected
[self.navigationController dismissModalViewControllerAnimated:NO];
[[UIApplication sharedApplication] setStatusBarHidden:NO animated:NO];
and th-th-that’s all folks!
Continue Reading →
29
DEC
Share