То, что я сделал, это так.Надеюсь, это поможет вам.
VC:UIViewController
{
@IBAction func test(_ sender: Any){
navigationController?.delegate = self
let destine = storyboard?.instantiateViewController(withIdentifier: "target")
navigationController?.pushViewController(destine!, animated: true)
}
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?{
return Traistion()
}
}
class Traistion: NSObject, UIViewControllerAnimatedTransitioning{
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let animator = transitionAnimator(using: transitionContext)
animator.startAnimation()
}
var animator: UIViewPropertyAnimator!
var context: UIViewControllerContextTransitioning!
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval{
return 1.0
}
enum Direction {
case down
case top
case left
case right
}
var from : Direction = .left
var auxCancelCompletion :(()->())? = {
return nil
}()
var auxAnimationsCancel :(()->())? = {
return nil
}()
var auxEndCompletion :(()->())? = {
return nil
}()
var auxAnimations : (()->())?
func transitionAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating {
let duration = transitionDuration(using: transitionContext)
let container = transitionContext.containerView
let toController = transitionContext.viewController(forKey: .to)
toController?.beginAppearanceTransition(true, animated: true)
guard
let to = transitionContext.view(forKey: .to),
let from = transitionContext.view(forKey: .from)
else {
print("To or from view are nil!")
fatalError()
}
container.addSubview(to)
let animator = UIViewPropertyAnimator(duration: duration, curve: .linear)
var toStartingPoint: CGPoint
var fromEndingPoint: CGPoint
switch self.from {
case .down:
toStartingPoint = CGPoint(x: 0, y: -from.bounds.height)
fromEndingPoint = CGPoint(x: 0, y: from.bounds.height)
case .top:
toStartingPoint = CGPoint(x: 0, y: from.bounds.height)
fromEndingPoint = CGPoint(x: 0, y: -from.bounds.height)
case .right:
toStartingPoint = CGPoint(x: from.bounds.width, y: 0)
fromEndingPoint = CGPoint(x: -from.bounds.width, y: 0)
case .left:
toStartingPoint = CGPoint(x: -from.bounds.width, y: 0)
fromEndingPoint = CGPoint(x: from.bounds.width, y: 0)
}
to.transform = CGAffineTransform(translationX: toStartingPoint.x, y: toStartingPoint.y)
animator.addAnimations({
from.transform = CGAffineTransform(translationX: fromEndingPoint.x, y: fromEndingPoint.y)
}, delayFactor: 0.0)
animator.addAnimations({
to.transform = .identity
}, delayFactor: 0.0)
animator.addCompletion { [weak self] position in
switch position {
case .start:
self?.auxCancelCompletion?()
transitionContext.completeTransition(false)
self?.auxAnimationsCancel?()
case .end:
self?.auxEndCompletion?()
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
from.transform = .identity
to.transform = .identity
default:
transitionContext.completeTransition(false)
self?.auxAnimationsCancel?()
}
}
if let auxAnimations = auxAnimations {
animator.addAnimations(auxAnimations)
}
self.animator = animator
self.context = transitionContext
animator.addCompletion { [unowned self] _ in
//self.animator = nil
// self.context = nil
}
animator.isUserInteractionEnabled = true
return animator
}
}
При использовании interruptibleAnimator
.Эта функция будет вызываться по крайней мере дважды, и вы должны предоставить один и тот же аниматор, но другой.Таким образом, вы должны назвать это так:
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
animator = transitionAnimator(using: transitionContext) as! UIViewPropertyAnimator
animator.startAnimation()
}
func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating {
return animator
}
var animator: UIViewPropertyAnimator!
var context: UIViewControllerContextTransitioning!
или проще так:
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
}
func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating {
if animator == nil {animator = transitionAnimator(using: transitionContext) as! UIViewPropertyAnimator
animator.startAnimation()}
return animator
}
Здесь animator
будет вызван дважды, и это то же самое.Если
func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating {
return transitionAnimator(using: transitionContext) }
Это неправильный способ использования, поскольку аниматор будет другим.
https://developer.apple.com/documentation/uikit/uiviewcontrolleranimatedtransitioning/1829434-interruptibleanimator
См. Последнюю строку в документе.