我正在使用动画过渡在聊天应用程序中显示图像。我将以下动画师类用作过渡对象。
大多数情况下,过渡效果良好且非常顺利。在任何情况下,都非常适合过渡到imageViewController以显示图像。但是,有时候向后过渡时,tableView contentOffset发生了变化,并且图像不再过渡回正确的位置。
我想要的是使用.overCurrentContext进行此过渡,但是当我尝试返回动画可以正常工作,但随后删除原始tableView时,屏幕变黑了。即使我将变量self.definesPresentationContext设置为true。
尝试了几天后,我放弃了overCurrentContext,所以现在我只是想弄清为什么tableView有时会更改偏移量以及如何解决该偏移量。或者,如果有更好的方法来实现过渡,以在另一个viewController中显示图像。
import UIKit
class Animator: NSObject, UIViewControllerAnimatedTransitioning {
private var image: UIImage?
private var fromDelegate: ImageTransitionProtocol?
private var toDelegate: ImageTransitionProtocol?
// MARK: Setup Methods
func setupImageTransition(image: UIImage, fromDelegate: ImageTransitionProtocol, toDelegate: ImageTransitionProtocol) {
self.image = image
self.fromDelegate = fromDelegate
self.toDelegate = toDelegate
}
// MARK: UIViewControllerAnimatedTransitioning
// 1: Set animation speed
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.6
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
// 2: Get view controllers involved
let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
// 3: Set the destination view controllers frame
//toVC.view.frame = fromVC.view.frame
toVC.view.frame = transitionContext.finalFrame(for: toVC)
// 4: Create transition image view
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.frame = (fromDelegate == nil) ? CGRect() : fromDelegate!.imageWindowFrame()
imageView.clipsToBounds = true
containerView.addSubview(imageView)
// 5: Create from screen snapshot
fromDelegate!.transitionSetup()
toDelegate!.transitionSetup()
let fromSnapshot = fromVC.view.snapshotView(afterScreenUpdates: true)!
fromSnapshot.frame = fromVC.view.frame
containerView.addSubview(fromSnapshot)
// 6: Create to screen snapshot
let toSnapshot = toVC.view.snapshotView(afterScreenUpdates: true)!
toSnapshot.frame = fromVC.view.frame
containerView.addSubview(toSnapshot)
toSnapshot.alpha = 0
// 7: Bring the image view to the front and get the final frame
containerView.bringSubview(toFront: imageView)
let toFrame = (self.toDelegate == nil) ? CGRect() : self.toDelegate!.imageWindowFrame()
// 8: Animate change
UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.8, options: .curveEaseOut, animations: {
toSnapshot.alpha = 1
imageView.frame = toFrame
}, completion:{ [weak self] (finished) in
self?.toDelegate!.transitionCleanup()
self?.fromDelegate!.transitionCleanup()
// 9: Remove transition views
imageView.removeFromSuperview()
fromSnapshot.removeFromSuperview()
toSnapshot.removeFromSuperview()
// 10: Complete transition
if !transitionContext.transitionWasCancelled {
containerView.addSubview(toVC.view)
}
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
}
}
protocol ImageTransitionProtocol {
func transitionSetup()
func transitionCleanup()
func imageWindowFrame() -> CGRect
}
以及tableViewController中的代码:
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let imagePresentationViewController = (presented as! UINavigationController).topViewController as! ImagePresentationViewController
self.transition.setupImageTransition( image: pickedImageForTransition!,
fromDelegate: self,
toDelegate: imagePresentationViewController)
return transition
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let imagePresentationViewController = (dismissed as! UINavigationController).topViewController as! ImagePresentationViewController
transition.setupImageTransition( image: pickedImageForTransition!,
fromDelegate: imagePresentationViewController,
toDelegate: self)
return transition
}