浏览代码

pre iOS15 fallback: implement swipe to dismiss for ViewControllers presented by PartialScreenPresentationController

cyberta 2 年之前
父节点
当前提交
644f4cdefc
共有 1 个文件被更改,包括 50 次插入8 次删除
  1. 50 8
      deltachat-ios/Controller/PartialScreenPresentationController.swift

+ 50 - 8
deltachat-ios/Controller/PartialScreenPresentationController.swift

@@ -3,21 +3,63 @@ import UIKit
 
 class PartialScreenPresentationController: UIPresentationController {
     let blurEffectView: UIVisualEffectView
-    var tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer()
+    private var direction: CGFloat = 0
+
+    lazy var tapGestureRecognizer: UITapGestureRecognizer = {
+        return UITapGestureRecognizer(target: self, action: #selector(dismiss))
+    }()
+
+    lazy var panGestureRecognizer: UIPanGestureRecognizer = {
+        return UIPanGestureRecognizer(target: self, action: #selector(didPan(pan:)))
+    }()
+
     @objc func dismiss() {
         self.presentedViewController.dismiss(animated: true, completion: nil)
     }
     
+    @objc func didPan(pan: UIPanGestureRecognizer) {
+            guard let view = pan.view, let superView = view.superview,
+                let presented = presentedView, let container = containerView else { return }
+
+            let location = pan.translation(in: superView)
+            let velocity = pan.velocity(in: superView)
+
+            let maxPresentedY = container.frame.height / 2
+            switch pan.state {
+            case .changed:
+                if location.y < 0 {
+                    break
+                }
+                presented.frame.origin.y =  maxPresentedY + location.y
+            case .ended:
+                if velocity.y > 100 && location.y  > 0 {
+                    presentedViewController.dismiss(animated: true, completion: nil)
+                } else {
+                    let offset = maxPresentedY + (maxPresentedY / 3)
+                    switch presented.frame.origin.y {
+                    case 0...offset:
+                        UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveEaseInOut, animations: {
+                            presented.frame.origin.y = maxPresentedY
+                        })
+                    default:
+                        presentedViewController.dismiss(animated: true, completion: nil)
+                    }
+                }
+            default:
+                break
+            }
+        }
+
     override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
         let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.dark)
-           blurEffectView = UIVisualEffectView(effect: blurEffect)
-           super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
-           tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.dismiss))
-           blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
-           self.blurEffectView.isUserInteractionEnabled = true
-           self.blurEffectView.addGestureRecognizer(tapGestureRecognizer)
+        blurEffectView = UIVisualEffectView(effect: blurEffect)
+        super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
+        blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+        blurEffectView.isUserInteractionEnabled = true
+        blurEffectView.addGestureRecognizer(tapGestureRecognizer)
+        presentedViewController.view.addGestureRecognizer(panGestureRecognizer)
     }
-    
+
    override var frameOfPresentedViewInContainerView: CGRect {
        guard let containerView = self.containerView else {
            return CGRect()