Is there a way to add a button at the corner of an UIModalPresentationPageSheet? I mean, I want to put that Apple-like (x) button at the corner of a Page Sheet, but adding it to the parent view makes it appear behind the Page Sheet (and also impossible to tap) and adding it to the Page Sheet will make part of it hidden, since it's out of the view area.
Is there a solution?
Thanks.
Here's a solution that I use. It's not quite what you describe, which would be neat too, but would be tricky since you'd want the button to be partially out of the view's bounds (as you say, it would have to be a child of the view-controller-view's superview).
My solution is to put a close button in the left-button area of a navigation bar. I do this automagically via a UIViewController class extension. To use it, just call [currentViewController presentAutoModalViewController: modalViewController animated: YES];
@implementation UIViewController (Modal)
- (void) presentAutoModalViewController: (UIViewController *) modalViewController withDismissAction: (SEL) onDismiss animated:(BOOL)animated
{
UINavigationController* nc = nil;
if ( NO == [ modalViewController isKindOfClass: [UINavigationController class]] )
{
nc = [[[UINavigationController alloc] initWithRootViewController: modalViewController] autorelease];
[nc setToolbarHidden:YES animated: NO];
nc.modalPresentationStyle = modalViewController.modalPresentationStyle;
modalViewController.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop
target:self
action:onDismiss] autorelease];
}
else
{
nc = (UINavigationController*) modalViewController;
UIViewController* rootViewController = [nc.viewControllers objectAtIndex: 0];
rootViewController.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop
target:self
action:onDismiss] autorelease];
}
[nc setNavigationBarHidden: NO];
nc.navigationBar.barStyle = UIBarStyleBlack;
nc.toolbar.barStyle = self.navigationController.navigationBar.barStyle;
[self presentModalViewController: nc animated: animated ];
}
- (void) presentAutoModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
{
[self presentAutoModalViewController:modalViewController withDismissAction: @selector(autoModalViewControllerDismiss:) animated: animated];
}
- (void) autoModalViewControllerDismiss: (id)sender
{
[self dismissModalViewControllerAnimated:YES];
}
- (BOOL) isAutoModalViewController
{
return ( self.navigationController != nil && self.navigationController.parentViewController != nil && self.navigationController.parentViewController.modalViewController == self.navigationController );
}
@end
EDIT: Actually, the first thing I would suggest you do is use a different kind of close button. You can, for example, add a toolbar at the top with a Done
button.
If you still want the Apple-style floating X, then try setting properties to make sure it doesn't get hidden or clipped. I would say the better way to do this would be to create a UIButton
with a foreground image which is the styled button image, and a background image which fades from the background colour/patterns of the page sheet to a transparent background around the button. It effectively gives you a "floating close button" without having to go outside the bounds of the page sheet.
I found @TomSwift's suggestion very helpful. Here is a version that uses the non-deprecated iOS7 methods and ARC.
@implementation UIViewController (Modal)
- (void)presentAutoModalViewController: (UIViewController *) modalViewController withDismissAction:(SEL) onDismiss animated:(BOOL)animated
{
UINavigationController* nc = nil;
if ( NO == [ modalViewController isKindOfClass: [UINavigationController class]] )
{
nc = [[UINavigationController alloc] initWithRootViewController: modalViewController];
[nc setToolbarHidden:YES animated: NO];
nc.modalPresentationStyle = modalViewController.modalPresentationStyle;
modalViewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop
target:self
action:onDismiss];
}
else
{
nc = (UINavigationController*) modalViewController;
UIViewController* rootViewController = [nc.viewControllers objectAtIndex: 0];
rootViewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop
target:self
action:onDismiss];
}
[nc setNavigationBarHidden: NO];
nc.navigationBar.barStyle = UIBarStyleBlack;
nc.toolbar.barStyle = self.navigationController.navigationBar.barStyle;
[self presentViewController:nc animated:animated completion:nil];
}
- (void)presentAutoModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
{
[self presentAutoModalViewController:modalViewController withDismissAction: @selector(autoModalViewControllerDismiss:) animated: animated];
}
- (void)autoModalViewControllerDismiss: (id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (BOOL)isAutoModalViewController
{
return ( self.navigationController != nil && self.navigationController.parentViewController != nil && self.navigationController.parentViewController.presentedViewController == self.navigationController );
}
@end
And I call it like...
MyController *vc = [[MyController alloc] init];
vc.modalPresentationStyle = UIModalPresentationFormSheet;
vc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentAutoModalViewController:info animated:YES];