簡體   English   中英

使用任何手勢關閉 UIPopoverPresentationController,而不僅僅是點擊

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

所以我有一個簡單的 UIPopoverPresentationController 來顯示一些內容。

用戶可以通過點擊屏幕上的任意位置來關閉它(默認彈出行為)。

如果用戶在屏幕上進行任何類型的點擊或手勢,我希望彈出窗口被關閉。 最好是拖動手勢。

知道這是否可能嗎? 如何?

嘗試使用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 是彈出窗口中顯示的視圖。 在 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];
                }
            }
}];

你有一個 UIDimmingView ,它包含將關閉的點擊手勢。 只需添加它。 我正在使用Class dimmingViewClass = NSClassFromString(@"UIDimmingView"); 避免直接使用未記錄的 API。 我還沒有嘗試將這個 hack 發送給蘋果,但下周會嘗試。 我希望它會過去。 但是我對此進行了測試,它確實調用了我的選擇器。

我使用自定義視圖解決了這個問題:

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

我對這個問題的解決方案。 例如,如果您創建一個名為MyPopoverViewController的類 UIViewController 來呈現 PopViewController。 然后在 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()
    }
}

然后在此 PopOverViewController 呈現的主 ViewController 中,實現協議的方法。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM