简体   繁体   English

在外部点击iOS 8上关闭模式表单表视图

[英]Dismiss modal form sheet view on outside tap iOS 8

I've been trying to dismiss the modal form sheet view on outside tap on iOS 8 with no luck, I've tried this code 我一直试图在iOS 8的外部点击上忽略模态表单视图而没有运气,我试过这段代码

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];

- (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];
    }
 }
}

But it doesn't detect outside view clicks, any suggestions ? 但它没有检测到外部视图点击,任何建议?

There are actually two problems in iOS 8. First, the gesture recognition does not begin. iOS 8中实际上存在两个问题。首先,手势识别不会开始。

I solved this by adding the UIGestureRecognizerDelegate protocol and implementing 我通过添加UIGestureRecognizerDelegate协议并实现来解决这个问题

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
{
    return YES;
}

Also, don't forget to register the delegate with 另外,不要忘记注册代表

recognizer.delegate = self;

Now the gesture recognizer should recognize gestures and the target method ( handleTapBehind: ) will be called. 现在,手势识别器应该识别手势,并且将调用目标方法( handleTapBehind:

Here comes the second problem in iOS 8: locationInView: doesn't seem to take the device orientation into account if nil is passed as a view. 这是iOS 8中的第二个问题: locationInView:如果将nil作为视图传递,则似乎不考虑设备方向。 Instead, passing the root view works. 相反,传递根视图是有效的。

Here's my target code that seems to work for iOS 7.1 and 8.0: 这是我的目标代码,似乎适用于iOS 7.1和8.0:

if (sender.state == UIGestureRecognizerStateEnded) {
    UIView *rootView = self.view.window.rootViewController.view;
    CGPoint location = [sender locationInView:rootView];
    if (![self.view pointInside:[self.view convertPoint:location fromView:rootView] withEvent:nil]) {
        [self dismissViewControllerAnimated:YES completion:^{
            [self.view.window removeGestureRecognizer:sender];
        }];
    }
}

In iOS 8, You can look at using the new UIPresentationController class. 在iOS 8中,您可以查看使用新的UIPresentationController类。 It gives you better control over the container around your custom view controller presentation (allowing you to correctly add a gesture recogniser of your own). 它使您可以更好地控制自定义视图控制器演示文稿周围的容器(允许您正确添加自己的手势识别器)。

Here is a link to quite a simple tutorial as well: http://dativestudios.com/blog/2014/06/29/presentation-controllers/ 这里有一个非常简单的教程的链接: http//dativestudios.com/blog/2014/06/29/presentation-controllers/

Then add the dimming view tap-to-dismiss: 然后添加调光视图tap-to-dismiss:

    UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
    [self.dimmingView addGestureRecognizer:singleFingerTap];


- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer {
    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}

Swift 3.1 solution that works in both portrait and landscape. Swift 3.1解决方案,适用于纵向和横向。

class TapBehindModalViewController: UIViewController, UIGestureRecognizerDelegate {
    private var tapOutsideRecognizer: UITapGestureRecognizer!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        if(self.tapOutsideRecognizer == nil) {
            self.tapOutsideRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTapBehind))
            self.tapOutsideRecognizer.numberOfTapsRequired = 1
            self.tapOutsideRecognizer.cancelsTouchesInView = false
            self.tapOutsideRecognizer.delegate = self
            self.view.window?.addGestureRecognizer(self.tapOutsideRecognizer)
        }
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        if(self.tapOutsideRecognizer != nil) {
            self.view.window?.removeGestureRecognizer(self.tapOutsideRecognizer)
            self.tapOutsideRecognizer = nil
        }
    }

    func close(sender: AnyObject) {
        self.dismiss(animated: true, completion: nil)
    }

    // MARK: - Gesture methods to dismiss this with tap outside
    func handleTapBehind(sender: UITapGestureRecognizer) {
        if (sender.state == UIGestureRecognizerState.ended) {
            let location: CGPoint = sender.location(in: self.view)

            if (!self.view.point(inside: location, with: nil)) {
                self.view.window?.removeGestureRecognizer(sender)
                self.close(sender: sender)
            }
        }
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM