用任何手势解雇UIPopoverPresentationController,而不仅仅是点击

时间:2017-02-07 10:08:29

标签: ios swift uigesturerecognizer

所以我有一个简单的UIPopoverPresentationController来显示一些内容。

用户可以通过点击屏幕上的任意位置来忽略它(默认弹出行为)。

如果用户在屏幕上进行任何类型的点按或手势,我希望解除弹出窗口。优选拖动手势。

知道这是否可行?怎么样?

4 个答案:

答案 0 :(得分:1)

尝试使用touchesBegan:withEvent方法

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if let touch = touches.first {
            if touch.view == self.view {
                self.dismiss()
            } else {
                return
            }

        }
    }

答案 1 :(得分:0)

VC是popover中显示的视图。 在presentViewController中:animated:completion:block

[self presentViewController:vc animated:YES completion:^{
UIView *v1 = vc.view.superview.superview.superview;

            for (UIView* vx in v1.subviews) {
                Class dimmingViewClass =  NSClassFromString(@"UIDimmingView");
                if ([vx isKindOfClass:[dimmingViewClass class]])
                {
                    UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(closePopoverOnSwipe)];
                    [vx addGestureRecognizer:pan];
                }
            }
}];

你有一个UIDimmingView,它可以保存将要关闭的点按手势。只是添加它。我使用Class dimmingViewClass = NSClassFromString(@"UIDimmingView");来避免直接使用未记录的API。我还没有尝试过将这个黑客发送给苹果,但下周会尝试。我希望它会过去。但我测试了它,它确实调用了我的选择器。

答案 2 :(得分:0)

我使用自定义视图解决了此问题:

typealias Handler = (() -> Void)?


final class InteractionView: UIView {

    var dismissHandler: Handler = nil

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        return self
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.dismissHandler?()
    }
}

在viewDidAppear中配置此视图并添加到popover containerView:

fileprivate func configureInteractionView() {
    let interactionView = InteractionView(frame: self.view.bounds)
    self.popoverPresentationController?.containerView?.addSubview(interactionView)
    interactionView.backgroundColor = .clear
    interactionView.isUserInteractionEnabled = true
    interactionView.dismissHandler = { [weak self] in
        self?.hide()
    }
}

fileprivate func hide() {
    self.dismiss(animated: true, completion: nil)
}

答案 3 :(得分:0)

我对这个问题的解决方案。 例如,如果您创建一个名为 MyPopoverViewController 的UIViewController类来呈现PopViewController。 然后在viewDidLoad()或viewWillAppear(_ animation :)方法中添加两个GestureRecognizer,如下所示:

protocal MyPopoverControllerDelegate {
    func shouldDismissPopover()
}

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

    // back trace to root view, if it is a UIWindows, add PanGestureRecognizer
    // and LongPressGestureRecognizer, to dismiss this PopoverViewController
    for c in sequence(first: self.view, next: { $0.superview}) {
        if let w = c as? UIWindow {

            let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(dismissPopover(gesture:)))
            w.addGestureRecognizer(panGestureRecognizer)

            let longTapGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(dismissPopover(gesture:)))
            w.addGestureRecognizer(longTapGestureRecognizer)
        }
    }

    @objc private func dismissPopover(gesture: UIGestureRecognizer) {
        delegate?.shouldDismissPopover()
    }
}

然后在此PopOverViewController呈现的主ViewController中,实现协议的方法。

extension YourMainViewController: MyPopoverControllerDelegate {
    func shouldDismissPopover() {
        self.presentedViewController?.dismiss(animated: true, completion: nil)
    }
}