Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iphone SDK dismissing Modal ViewControllers on ipad by clicking outside of it

I want to dismiss a FormSheetPresentation modal view controller when the user taps outside the modal view...I have seen a bunch of apps doing this (ebay on ipad for example) but i cant figure out how since the underneath views are disabled from touches when modal views are displayed like this (are they presenting it as a popover perhaps?)...anyone have any suggestions?

like image 777
Daniel Avatar asked Apr 12 '10 15:04

Daniel


2 Answers

I'm a year late, but this is pretty straightforward to do.

Have your modal view controller attach a gesture recognizer to the view's window:

UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapBehind:)];  [recognizer setNumberOfTapsRequired:1]; recognizer.cancelsTouchesInView = NO; //So the user can still interact with controls in the modal view [self.view.window addGestureRecognizer:recognizer]; [recognizer release]; 

The handling code:

- (void)handleTapBehind:(UITapGestureRecognizer *)sender {     if (sender.state == UIGestureRecognizerStateEnded)      {        CGPoint location = [sender locationInView:nil]; //Passing nil gives us coordinates in the window   //Then we convert the tap's location into the local view's coordinate system, and test to see if it's in or outside. If outside, dismiss the view.          if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil])          {            // Remove the recognizer first so it's view.window is valid.           [self.view.window removeGestureRecognizer:sender];           [self dismissModalViewControllerAnimated:YES];         }      } } 

That's about it. HIG be damned, this is a useful and often intuitive behavior.

like image 81
Danilo Campos Avatar answered Sep 28 '22 10:09

Danilo Campos


For iOS 8, you must both implement the UIGestureRecognizer, and swap the (x,y) coordinates of the tapped location when in landscape orientation. Not sure if this is due to an iOS 8 bug.

- (void) viewDidAppear:(BOOL)animated {     [super viewDidAppear:animated];      // add gesture recognizer to window      UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapBehind:)];     [recognizer setNumberOfTapsRequired:1];     recognizer.cancelsTouchesInView = NO; //So the user can still interact with controls in the modal view     [self.view.window addGestureRecognizer:recognizer];     recognizer.delegate = self; }  - (void)handleTapBehind:(UITapGestureRecognizer *)sender {     if (sender.state == UIGestureRecognizerStateEnded) {          // passing nil gives us coordinates in the window         CGPoint location = [sender locationInView:nil];          // swap (x,y) on iOS 8 in landscape         if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {             if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {                 location = CGPointMake(location.y, location.x);             }         }          // convert the tap's location into the local view's coordinate system, and test to see if it's in or outside. If outside, dismiss the view.         if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil]) {              // remove the recognizer first so it's view.window is valid             [self.view.window removeGestureRecognizer:sender];             [self dismissViewControllerAnimated:YES completion:nil];         }     } }   #pragma mark - UIGestureRecognizer Delegate  - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {     return YES; }  - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {     return YES; }  - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {     return YES; } 
like image 39
Erich Avatar answered Sep 28 '22 09:09

Erich