简体   繁体   English

与平移手势不同步的拖放交互过渡

[英]Drag-to-dismiss interactive transition out of sync with pan gesture

I am trying to implement a custom drag-to-dismiss interactive transition, using UIViewControllerAnimatedTransitioning and UIPercentDrivenInteractiveTransition .我正在尝试使用UIViewControllerAnimatedTransitioningUIPercentDrivenInteractiveTransition来实现自定义的拖放交互过渡。

Here is the animator code for dismissing, it just moves the view down completely out from the frame:这是用于解散的动画师代码,它只是将视图从框架中完全向下移动:

final class SheetDismissAnimator: NSObject, UIViewControllerAnimatedTransitioning {

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

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let fromVC = transitionContext.viewController(forKey: .from) else { return }

        UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
            fromVC.view.frame.origin.y = transitionContext.containerView.frame.height
        }, completion: { _ in
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        })
    }

}

And here is the code for the modal view controller I am trying to dismiss, which has the pan gesture recognizer attached to it:这是我试图关闭的模态视图控制器的代码,它附加了平移手势识别器:

final class ModalViewController: UIViewController {

    private let customTransitionDelegate = SheetTransitioningDelegate()
    private var interactionController: UIPercentDrivenInteractiveTransition?

    init() {
        super.init(nibName: nil, bundle: nil)

        modalPresentationStyle = .custom
        transitioningDelegate = customTransitionDelegate
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .red
        view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handleGesture(_:))))
    }

    @objc func handleGesture(_ gesture: UIPanGestureRecognizer) {
        let translate = gesture.translation(in: view)
        let percent   = translate.y / view.bounds.height

        switch gesture.state {
        case .began:
            interactionController = UIPercentDrivenInteractiveTransition()
            customTransitionDelegate.interactionController = interactionController
            dismiss(animated: true)
        case .changed:
            interactionController?.update(percent)
        case .cancelled:
            interactionController?.cancel()
        case .ended:
            let velocity = gesture.velocity(in: gesture.view)
            if percent > 0.5 || velocity.y > 700 {
                interactionController?.finish()
            } else {
                interactionController?.cancel()
            }
            interactionController = nil
        default:
            break
        }

    }
}

The relevant part I believe is the handleGesture(_ gesture: UIPanGestureRecognizer) function, which calculates the percentage for advancing the animation.我相信相关部分是handleGesture(_ gesture: UIPanGestureRecognizer)函数,它计算推进动画的百分比。 Pasted the whole code for clarity.为了清楚起见,粘贴了整个代码。

I would expect the animation to follow the pan gesture linearly, but this is what happens instead:我希望动画线性地跟随平移手势,但这是发生的事情:

https://media.giphy.com/media/Wn6kAgngfHeynjhAbm/giphy.gif

I solved the issue by switching to UIViewPropertyAnimator :我通过切换到UIViewPropertyAnimator解决了这个问题:

final class SheetDismissAnimator: NSObject, UIViewControllerAnimatedTransitioning {

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

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let propertyAnimator = UIViewPropertyAnimator(duration: transitionDuration(using: transitionContext),
                                                  timingParameters: UISpringTimingParameters(dampingRatio: 1))
        propertyAnimator.addAnimations {
            switch self.type {
            case .presented:
                guard let toVC = transitionContext.viewController(forKey: .to) else { break }
                toVC.view.frame = transitionContext.finalFrame(for: toVC)
            case .dismissed:
                transitionContext.view(forKey: .from)?.frame.origin.y = transitionContext.containerView.frame.maxY
            }
        }
        propertyAnimator.addCompletion { _ in
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }

        propertyAnimator.startAnimation()
    }

}

I also added the following into my gesture handling code, which is a basic attempt at transfering the gesture's velocity to the animation speed.我还在我的手势处理代码中添加了以下内容,这是将手势速度转换为动画速度的基本尝试。

case .ended:
    if percent > 0.45 || velocity.y > 700 {
        interactor.timingCurve = UICubicTimingParameters(animationCurve: .linear)
        interactor.completionSpeed = max(1, (view.frame.height * (1 / interactor.duration) / velocity.y))
        interactor.finish()
    } else {
        interactor.cancel()
    }
    isInteractive = false

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

相关问题 ViewController 交互式过渡平移手势识别器 - ViewController Interactive transition pan gesture recognizer 由夹点和平移手势识别器同时触发的交互式ViewController转换 - Interactive ViewController transition triggered by pinch and pan gesture recognisers simultaneously 在 nativescript 核心上使用平移手势自定义过渡 - Custom transition using pan gesture on nativescript core 如何基于Pan手势放大/缩小UIView? - How to Zoom in/out an UIView based on Pan gesture? 如果检测到越界,则禁用Pan Gesture - Disabling Pan Gesture if out of bounds detected 摇动手势开始后,交互式滑动菜单即完成[Swift] - Interactive sliding menu goes to completion as soon as pan gesture starts [Swift] UIViewController 交互式过渡 - 取消交互式关闭时显示的视图消失 - UIViewController interactive transition - Presented view disappears when interactive dismiss is canceled 使用UIDynamicAnimator的平移手势拖动UIView的正确方法 - Correct way to drag a UIView around with a pan gesture with a UIDynamicAnimator 使用滑动手势关闭底页时如何防止键盘关闭(交互式关闭)iOS - How to prevent keyboard dismiss when bottomsheet is dismiss using swipe gesture (Interactive dismiss) iOS 在Snapchat等相机上平移手势(按住/拖动) - Pan gesture (hold/drag) zoom on camera like Snapchat
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM