[英]Drag-to-dismiss interactive transition out of sync with pan gesture
我正在嘗試使用UIViewControllerAnimatedTransitioning
和UIPercentDrivenInteractiveTransition
來實現自定義的拖放交互過渡。
這是用於解散的動畫師代碼,它只是將視圖從框架中完全向下移動:
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)
})
}
}
這是我試圖關閉的模態視圖控制器的代碼,它附加了平移手勢識別器:
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
}
}
}
我相信相關部分是handleGesture(_ gesture: UIPanGestureRecognizer)
函數,它計算推進動畫的百分比。 為了清楚起見,粘貼了整個代碼。
我希望動畫線性地跟隨平移手勢,但這是發生的事情:
我通過切換到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()
}
}
我還在我的手勢處理代碼中添加了以下內容,這是將手勢速度轉換為動畫速度的基本嘗試。
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.