【问题标题】:Interactive sliding menu goes to completion as soon as pan gesture starts [Swift]平移手势一开始,交互式滑动菜单就完成[Swift]
【发布时间】:2018-07-14 20:10:31
【问题描述】:

我正在尝试实现一个滑动菜单,该菜单可以通过水平平移以交互方式关闭,与 Uber 和 Google 应用程序中的菜单相同。一切都按预期进行,只是一旦我开始水平平移,无需跟随我的手指就可以完成关闭。非常感谢您对问题所在的任何建议。

我将UIPresentationController 子类化以定义我的菜单控制器的显示宽度。我有自定义演示动画师和解雇动画师,还有一个UIViewControllerTransitioningDelegate 对象将它们全部返回给UIKit。我还在菜单控制器中实现了gestureRecognizerShouldBegin(_ gestureRecognizer:) 方法以允许垂直滚动。

SlideDismissAnimator

class SlideDismissAnimator: NSObject, UIViewControllerAnimatedTransitioning {

    let interactionController: SlideInteractionController?

    init(interactionController: SlideInteractionController?) {
        self.interactionController = interactionController
        super.init()
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.2
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

        let fromCV = transitionContext.viewController(forKey: .from)!

        let initialFrame = transitionContext.finalFrame(for: fromCV)
        var finalFrame = initialFrame
        finalFrame.origin.x = transitionContext.containerView.frame.width // My menu slides in from right

        let duration = transitionDuration(using: transitionContext)

        UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: {
            fromCV.view.frame = finalFrame
        }) { _ in
   transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }
    }
}

幻灯片交互控制器

class SlideInteractionController: UIPercentDrivenInteractiveTransition {

    var interactionInProgress = false

    private var shouldCompleteTransition = false
    private weak var collectionViewController: UICollectionViewController!

    init(collectionViewController: UICollectionViewController) {
        super.init()
        self.collectionViewController = collectionViewController
        if let menuController = collectionViewController as? MenuController {
            let gesture = UIPanGestureRecognizer(target: self, action: #selector(handleGesture))
            menuController.collectionView?.addGestureRecognizer(gesture)
            gesture.delegate = menuController
        }
    }

    @objc func handleGesture(_ gestureRecognizer: UIPanGestureRecognizer) {
        let translation = gestureRecognizer.translation(in: gestureRecognizer.view!.superview!)
        var progress = (translation.x / 100)
        progress = CGFloat(fminf(fmaxf(Float(progress), 0.0), 1.0))

        switch gestureRecognizer.state {
        case .began:
            interactionInProgress = true
            collectionViewController.dismiss(animated: true, completion: nil)

        case .changed:
            shouldCompleteTransition = progress > 0.5
            update(progress)

        case .cancelled:
            interactionInProgress = false
            cancel()

        case .ended:
            interactionInProgress = false
            if shouldCompleteTransition {
                finish()
            } else {
                cancel()
            }
        default:
            break
        }
    }
}

菜单控制器

class MenuController: UICollectionViewController, UIGestureRecognizerDelegate {

    var slideInteractionController: SlideInteractionController?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupView()
        slideInteractionController = SlideInteractionController(collectionViewController: self)
    }

    ...

    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        if let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer {
            let translation = panGestureRecognizer.translation(in: collectionView)
            if translation.x > fabs(translation.y) {
                return true
            }
        }
        return false
    }
}

【问题讨论】:

    标签: ios swift uipresentationcontroller dismissviewcontroller


    【解决方案1】:

    我制作了一个示例项目,该项目在视图中使用 tableView,该视图充当在当前上下文中呈现的侧菜单抽屉

    我的锅处理程序

    //MARK: Pan gesture Handler
        @objc func handlePanGesture(panGesture: UIPanGestureRecognizer)
        {
            ///Get the changes
            let translation = panGesture.translation(in: self.view)
    
            ///Make View move to left side of Frame
            if CGFloat(round(Double((panGesture.view?.frame.origin.x)!))) <= 0
            {
                panGesture.view!.center = CGPoint(x: panGesture.view!.center.x + translation.x, y: panGesture.view!.center.y)
                panGesture.setTranslation(CGPoint.zero, in: self.view)
            }
    
            ///Do not let View go beyond origin as 0
            if CGFloat(round(Double((panGesture.view?.frame.origin.x)!))) > 0
            {
                panGesture.view?.frame.origin.x = 0
                panGesture.setTranslation(CGPoint.zero, in: self.view)
            }
    
            ///States When Dragging
            switch panGesture.state
            {
            case .changed:
                self.setAlphaOfBlurView(origin: (panGesture.view?.frame.maxX)!)
    
            case .ended:
                if CGFloat(round(Double((panGesture.view?.frame.maxX)!))) >= self.view.frame.size.width*0.35
                {
                    UIView.animate(withDuration: 0.7, animations: {
                        panGesture.view?.frame.origin.x = 0
                        panGesture.setTranslation(CGPoint.zero, in: self.view)
                    })
                }
                else
                {
                    UIView.animate(withDuration: 0.4, animations: {
                        panGesture.view?.frame.origin.x -= self.maximum_x
                        panGesture.setTranslation(CGPoint.zero, in: self.view)
                    }, completion: { (success) in
                        if (success)
                        {
                            self.remove(asChildViewController: self.sideMenuVCObject, baseView: self.baseView)
                            self.baseView.removeFromSuperview()
                            self.blurView.removeFromSuperview()
    
                            //Remove Notification observer
                            NotificationCenter.default.removeObserver(self,name: NSNotification.Name(rawValue: "hideMenu"),object: nil)
                        }
                    })
                }
                break
            default:
                print("Default Case")
            }
        }
    

    GiHub 上的存储库链接

    https://github.com/RockinGarg/Slide-Menu-Drawer.git

    工作视频:

    https://drive.google.com/open?id=13Q-bBkVlAX7uEweDyQGvNct-dXkBSveT

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-20
      • 2020-02-11
      • 2016-05-15
      • 1970-01-01
      • 2020-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多