Интерактивное скользящее меню завершается, как только начинается панорамирование [Swift]

Я пытаюсь реализовать скользящее меню, которое можно интерактивно отклонить с помощью горизонтального панорамирования, как в приложениях 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)
        }
    }
}

SlideInteractionController

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

MenuController

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

1 ответ

Я сделал пример проекта, который использует tableView внутри View, который выступает в качестве бокового меню. Представлено в текущем контексте.

мой кастрюля обработчик

//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

Другие вопросы по тегам