我正在使用 UIViewControllerAnimatedTransitioning
和 UIPercentDrivenInteractiveTransition
以交互方式关闭模态呈现的 View Controller 。没什么特别的。但是我注意到在交互开始时偶尔会出现一个小故障。如果使用 .curveEaseOut
选项设置动画,它会变得更加明显。我正在关注的一些在线教程 ( https://www.thorntech.com/2016/02/ios-tutorial-close-modal-dragging/ ) 也会发生同样的事情。当我第一次向下拖动时,您可以看到 gif 中的故障。有什么建议吗?
MyDismissAnimator
class SlideInDismissAnimator: NSObject, UIViewControllerAnimatedTransitioning {
// ...
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let toVC = transitionContext.viewController(forKey: .to),
let presentedVC = transitionContext.viewController(forKey: .from) else {return}
let presentedFrame = transitionContext.finalFrame(for: presentedVC)
var dismissedFrame = presentedFrame
dismissedFrame.origin.y = transitionContext.containerView.frame.size.height
transitionContext.containerView.insertSubview(toVC.view, belowSubview: presentedVC.view)
}
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: {
presentedVC.view.frame = dismissedFrame
}) { _ in
if transitionContext.transitionWasCancelled {
toVC.view.removeFromSuperview()
}
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
}
我的交互器
class SwipeInteractionController: UIPercentDrivenInteractiveTransition {
var interactionInProgress = false
private var shouldCompleteTransition = false
private weak var viewController: UIViewController!
init(viewController: UIViewController) {
self.viewController = viewController
super.init()
let gesture = UIPanGestureRecognizer(target: self, action: #selector(handleGesture(_:)))
viewController.view?.addGestureRecognizer(gesture)
}
@objc func handleGesture(_ gestureRecognizer: UIPanGestureRecognizer) {
let translation = gestureRecognizer.translation(in: gestureRecognizer.view!.superview!)
var progress = (translation.y / viewController.view.bounds.height)
progress = CGFloat(fminf(fmaxf(Float(progress), 0.0), 1.0))
switch gestureRecognizer.state {
case .began:
interactionInProgress = true
viewController.dismiss(animated: true, completion: nil)
case .changed:
shouldCompleteTransition = progress > 0.3
update(progress)
case .cancelled:
interactionInProgress = false
cancel()
case .ended:
interactionInProgress = false
if shouldCompleteTransition {
finish()
} else {
cancel()
}
default:
break
}
}
}
最佳答案
我很确定这是 UIPercentDrivenInteractiveTransition 的错误,但我能够解决这个问题:
当调用 dismiss() 后没有尽快更新进度时会出现该错误。发生这种情况是因为平移手势识别器的 .changed 状态仅在您拖动时触发。因此,如果您缓慢拖动,在调用 .begin 和调用第一个 .changed 之间,关闭过渡将开始动画。
您可以在模拟器中看到这一点,方法是非常缓慢地逐像素拖动 View ,直到调用 .begin。只要 .changed 没有被再次调用,转换实际上会自行完成,您会看到 View 一直处于动画状态并完成转换。
但是,在 .dismiss() 之后简单地调用 update(progress) 也不起作用,我相信是因为 dismiss 动画还没有开始。 (直到下一个运行循环或其他东西)
我的“黑客”解决方案是在非常短的时间内分派(dispatch)异步,有效地设置进度并在动画开始前停止。
case .began:
interactionInProgress = true
viewController.dismiss(animated: true, completion: nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.001) {
self.update(progress)
}
关于ios - 以交互方式关闭模态视图 Controller 时出现故障,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48666523/