我正在尝试实现一个滑动菜单,该菜单可以通过水平平移以交互方式解除,与 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
}
}