@interface XXViewController (){ @property (strong, nonatomic) UITapGestureRecognizer *tapGesture; - (void)handleTapGesture:(UITapGestureRecognizer *)gesture; - (void)dismiss; @end @implementation XXViewController - (void)dismiss { [self dismissModalViewControllerAnimated:YES]; } - (void)viewDidAppear:(BOOL)animated { if (iPadIdiom) { if (self.tapGesture == nil) { UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]; self.tapGesture = tapGesture; } //将手势添加到 window 上 if ([self.view.window.gestureRecognizers containsObject:self.tapGesture] == NO) { [self.view.window addGestureRecognizer:self.tapGesture]; } } [super viewDidAppear:animated]; } - (void)viewWillDisappear:(BOOL)animated { //将手势从 window 上移除 if ([self.view.window.gestureRecognizers containsObject:self.tapGesture]) { [self.view.window removeGestureRecognizer:self.tapGesture]; } [super viewWillDisappear:animated]; } - (void)handleTapGesture:(UITapGestureRecognizer *)gesture { //因为是 TapGesture 的需要点击次数为 1,所以这个判断实际可以不写 if (gesture.state == UIGestureRecognizerStateEnded) { //传 nil,gesture 会返回触碰点在 windiow 上的值 CGPoint touchPoint = [gesture locationInView:nil]; //将得到的坐标转换成与 self.view 相对应的坐标 CGPoint convertPoint = [self.view convertPoint:touchPoint fromView:gesture.view]; //判断触碰点是否在 self.view。bounse 中,如果在则返回,否则调用 dismiss 方法 if (CGRectContainsPoint(self.view.bounds, convertPoint)) { return; } [self dismiss]; } } @end
############# 更新 2014年07月24日13:11:06 ###############
之前的方法处理之后会有个小问题,presented 的 ViewController 如果有个列表,无法拿到点击事件(Button 没有测试,不知是否一样)
解决办法:
http://stackoverflow.com/a/12851794
1.设置 tapGestureRecognizer
tapGesture.cancelsTouchesInView = NO;
2.设置 gestureRecognizer 的 delegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if([touch.view class] == tableview.class){ return //YES/NO } return //YES/NO }
3.用 UIControl 代替 tapGestureRecognizer
- (void)viewDidAppear:(BOOL)animated { if (iPadIdiom && self.dismissWhenTapOutsides) { if (tapControl == nil) { UIWindow *window = self.view.window; tapControl = [[UIControl alloc] initWithFrame:window.bounds]; tapControl.backgroundColor = [UIColor clearColor]; [window insertSubview:tapControl atIndex:[window.subviews count] - 1]; [tapControl addTarget:self action:@selector(dismissOnTap) forControlEvents:UIControlEventTouchDown]; } } [super viewDidAppear:animated]; } - (void)dismissOnTap { [self dismissViewControllerAnimated:YES completion:nil]; } - (void)viewWillDisappear:(BOOL)animated { //将手势从 window 上移除 if (self.dismissWhenTapOutsides) { if (tapControl && tapControl.superview) { [tapControl removeFromSuperview]; tapControl = nil; } } [super viewWillDisappear:animated]; }