简体   繁体   English

使用任何手势关闭 UIPopoverPresentationController,而不仅仅是点击

[英]Dismiss UIPopoverPresentationController with any gesture, not just tap

So I have a simple UIPopoverPresentationController that displays some content.所以我有一个简单的 UIPopoverPresentationController 来显示一些内容。

User can dismiss it by tapping anywhere on the screen (default popover behaviour).用户可以通过点击屏幕上的任意位置来关闭它(默认弹出行为)。

I want the popover to be dismissed if the user does any kind of tap or gesture on the screen.如果用户在屏幕上进行任何类型的点击或手势,我希望弹出窗口被关闭。 Preferably drag gesture.最好是拖动手势。

Any idea if this is possible?知道这是否可能吗? And how?如何?

try using touchesBegan:withEvent method尝试使用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
            }

        }
    }

VC is the view presented in the popover. VC 是弹出窗口中显示的视图。 in the presentViewController:animated:completion: block在 presentViewController:animated:completion: 块中

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

you have a UIDimmingView that holds the tap gesture that will close.你有一个 UIDimmingView ,它包含将关闭的点击手势。 just add to it.只需添加它。 I am using the Class dimmingViewClass = NSClassFromString(@"UIDimmingView");我正在使用Class dimmingViewClass = NSClassFromString(@"UIDimmingView"); to avoid making direct use of undocumented APIs.避免直接使用未记录的 API。 I have not tried yet to send this hack to apple, but will try next week.我还没有尝试将这个 hack 发送给苹果,但下周会尝试。 I hope it will pass.我希望它会过去。 But I tested this and it did call my selector.但是我对此进行了测试,它确实调用了我的选择器。

I resolved this problem using custom view:我使用自定义视图解决了这个问题:

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?()
    }
}

In the viewDidAppear configure this view and add to popover containerView:在 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)
}

my solution for this problem.我对这个问题的解决方案。 for example if you create a class UIViewController named MyPopoverViewController to present PopViewController.例如,如果您创建一个名为MyPopoverViewController的类 UIViewController 来呈现 PopViewController。 then in the viewDidLoad() or viewWillAppear(_ animated:) Method add two GestureRecognizer as follows:然后在 viewDidLoad() 或 viewWillAppear(_animated:) 方法中添加两个 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()
    }
}

then in your main ViewController, which this PopOverViewController presents, implements the Method of the Protocol.然后在此 PopOverViewController 呈现的主 ViewController 中,实现协议的方法。

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

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

相关问题 使用点击手势关闭 SVProgressHUD - Dismiss SVProgressHUD with Tap Gesture 如何用轻击手势关闭SDCAlertView? - How to dismiss SDCAlertView with tap gesture? 关闭UIPopOverPresentationcontroller - Dismiss UIPopOverPresentationcontroller 如何在其内部点击时关闭UIPopoverPresentationController。 (iOS,Swift) - How to dismiss UIPopoverPresentationController on tap inside it. (iOS, Swift) UIPopoverPresentationController不会在标题视图上禁用轻击手势 - UIPopoverPresentationController doesn't disable tap gesture on title view 点击手势以关闭键盘似乎要禁用didSelectRow - Tap Gesture To Dismiss Keyboard Seems To Disables didSelectRow 关闭时获取UIPopoverPresentationController事件 - Get event of UIPopoverPresentationController when dismiss 向任何视图添加点击手势不会触发任何操作 - Adding Tap Gesture to any view triggers nothing 当UITextField位于UIScrollView内时,使用“敲击手势”关闭键盘的问题。 - Issues with dismiss keyboard using Tap Gesture when UITextField is inside UIScrollView. 不要在iOS对话框区域之外用轻击手势关闭uialertcontroller工作表 - Don't dismiss uialertcontroller sheet with tap gesture outside dialog area in iOS
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM