Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dismiss modal view form sheet controller on outside tap

I am presenting a modal view controller as a form sheet and dismissing it when the cancel button, which is a bar button item, is clicked. I need to dismiss it when I tap on outside of that view. Please help me with a reference. Note: my modal view controller is presented with a navigation controller.

@cli_hlt, @Bill Brasky thanks for your answer. I need to dismiss it when tap occurs outside of the modal view which is a form sheet. I am pasting my code below.

-(void)gridView:(AQGridView *)gridView didSelectItemAtIndex:(NSUInteger)index   {             if(adminMode)      {         CHEditEmployeeViewController *editVC = [[CHEditEmployeeViewController alloc] initWithNibName:@"CHEditEmployeeViewController" bundle:nil];         editVC.delegate = self;         editVC.pickedEmployee = employee;         editVC.edit = TRUE;         editVC.delegate = self;         UINavigationController *navigationController = [[UINavigationController alloc]initWithRootViewController:editVC];         navigationController.modalPresentationStyle = UIModalPresentationFormSheet;         [self presentModalViewController:navigationController animated:YES];          return;     }   //the above code is from the view controller which presents the modal     view. Please look at the below code too which is from my modal view controller. Please guide me in a proper way.   -(void)tapGestureRecognizer {      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 addGestureRecognizer:recognizer];  }  - (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])          {             [self dismissModalViewControllerAnimated:YES];             [self.view.window removeGestureRecognizer:sender];         }      } } 
like image 577
jessy Avatar asked Feb 01 '12 20:02

jessy


People also ask

How do you dismiss a modal view controller?

According to the View Controller Programming guide for iPhone OS, this is incorrect when it comes to dismissing modal view controllers you should use delegation. So before presenting your modal view make yourself the delegate and then call the delegate from the modal view controller to dismiss.


1 Answers

I know this is an old question but this IS possible, despite of what the "right" answer says. Since this was the first result when I was looking for this I decided to elaborate:

This is how you do it:

You need to add a property to the View Controller from where you want to present modally, in my case "tapBehindGesture".

then in viewDidAppear

if(!tapBehindGesture) {         tapBehindGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapBehindDetected:)];         [tapBehindGesture setNumberOfTapsRequired:1];         [tapBehindGesture setCancelsTouchesInView:NO]; //So the user can still interact with controls in the modal view     }  [self.view.window addGestureRecognizer:tapBehindGesture]; 

And Here is the implementation for tapBehindDetected

- (void)tapBehindDetected:(UITapGestureRecognizer *)sender {      if (sender.state == UIGestureRecognizerStateEnded)     {         //(edited) not working for ios8 above          //CGPoint location = [sender locationInView:nil]; //Passing nil gives us coordinates in the window          CGPoint location = [sender locationInView: self.presentingViewController.view];          //Convert tap location into the local view's coordinate system. If outside, dismiss the view.         if (![self.presentedViewController.view pointInside:[self.presentedViewController.view convertPoint:location fromView:self.view.window] withEvent:nil])         {                if(self.presentedViewController) {                 [self dismissViewControllerAnimated:YES completion:nil];             }         }     } } 

Just remember to remove tapBehindGesture from view.window on viewWillDisappear to avoid triggering handleTapBehind in an unallocated object.

like image 155
Ares Avatar answered Oct 20 '22 00:10

Ares