Bu Google'daki en iyi sonuç olduğu için en aklı başında olduğunu düşündüğüm şeyi paylaşacağımı düşündüm; iOS 7+ geçiş API'sını kullanmaktır. Swift 3 ile iOS 10 için bunu uyguladım.
Bunu, UINavigationController
bir sınıfın alt sınıfını oluşturursanız UINavigationController
ve bir sınıfınUIViewControllerAnimatedTransitioning
Protokolle .
Örneğin benim UINavigationController
alt sınıfım:
class NavigationController: UINavigationController {
init() {
super.init(nibName: nil, bundle: nil)
delegate = self
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension NavigationController: UINavigationControllerDelegate {
public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return NavigationControllerAnimation(operation: operation)
}
}
Kendine ayarladığımı görebilirsiniz UINavigationControllerDelegate
ve alt sınıfımdaki bir uzantıda, UINavigationControllerDelegate
özel bir animasyon denetleyicisi (yani, NavigationControllerAnimation
) döndürmenize izin veren yöntemi uygularım . Bu özel animasyon denetleyicisi sizin için stok animasyonunun yerini alacak.
Muhtemelen NavigationControllerAnimation
başlatıcı aracılığıyla operasyona neden örneğe geçtiğimi merak ediyorsunuzdur . Bunu NavigationControllerAnimation
,UIViewControllerAnimatedTransitioning
(itme 'veya '' pop protokolü Ben operasyon yani) ne olduğunu biliyorum.' Bu ne tür bir animasyon yapmam gerektiğini bilmemize yardımcı olur. Çoğu zaman, işleme bağlı olarak farklı bir animasyon gerçekleştirmek istersiniz.
Gerisi oldukça standarttır. UIViewControllerAnimatedTransitioning
Protokolde gerekli iki işlevi uygulayın ve istediğiniz gibi canlandırın:
class NavigationControllerAnimation: NSObject, UIViewControllerAnimatedTransitioning {
let operation: UINavigationControllerOperation
init(operation: UINavigationControllerOperation) {
self.operation = operation
super.init()
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else { return }
let containerView = transitionContext.containerView
if operation == .push {
// do your animation for push
} else if operation == .pop {
// do your animation for pop
}
}
}
Her farklı işlem türü için (yani, 'itme' veya 'pop) için görünümden ve görünümden denetleyicilerin farklı olacağını hatırlamak önemlidir. Bir itme işlemindeyken, görüntüleme denetleyicisi itilen kumanda olacaktır. Bir pop işlemindeyken, görünüm denetleyicisi, geçiş yapılan denetleyici, ve görünüm denetleyicisi de patlatılan denetleyici olacaktır.
Ayrıca, to
görünüm denetleyicisi containerView
geçiş bağlamında alt görünümü olarak eklenmelidir .
Animasyonunuz tamamlandığında aramalısınız transitionContext.completeTransition(true)
. Etkileşimli bir geçiş yapıyorsanız, dinamik bir geri dönmek zorunda kalacak Bool
kadar completeTransition(didComplete: Bool)
geçiş animasyon sonunda tamamlanıp tamamlanmadığını bağlı.
Son olarak ( isteğe bağlı okuma ), üzerinde çalıştığım geçişi nasıl yaptığımı görmek isteyebilirsiniz. Bu kod biraz daha hacky ve ben oldukça hızlı bir şekilde yazdım, bu yüzden harika bir animasyon kodu olduğunu söyleyemem ama yine de animasyon parçasının nasıl yapılacağını gösterir.
Benimki gerçekten basit bir geçişti; UINavigationController'ın yaptığı gibi aynı animasyonu taklit etmek istedim, ancak 'üstte bir sonraki sayfa' animasyonu yerine, yeni görünümle aynı anda eski görünüm denetleyicisinin 1: 1 animasyonunu uygulamak istedim denetleyici görünür. Bu, iki görünüm kontrolörünün birbirine sabitlenmiş gibi görünmesini sağlar.
İtme işlemi için, önce toViewController
x ekseni kapalı ekranındaki görünümün başlangıcını ayarlamayı, alt görünümü olarak ekleyerek sıfıra containerView
ayarlayarak ekranda canlandırmayı gerektirir origin.x
. Aynı zamanda, ekranını kapatarak fromViewController
görüntüsünü uzaklara hareket ettiriyorum origin.x
:
toViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.size.width, dy: 0.0)
containerView.addSubview(toViewController.view)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: [ UIViewAnimationOptions.curveEaseOut ],
animations: {
toViewController.view.frame = containerView.bounds
fromViewController.view.frame = containerView.bounds.offsetBy(dx: -containerView.frame.size.width, dy: 0)
},
completion: { (finished) in
transitionContext.completeTransition(true)
})
Pop işlemi temelde tersidir. Ekle toViewController
bir subview containerView
ve uzak animasyon fromViewController
İçinde animasyon olarak sağa toViewController
soldan:
containerView.addSubview(toViewController.view)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: [ UIViewAnimationOptions.curveEaseOut ],
animations: {
fromViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.width, dy: 0)
toViewController.view.frame = containerView.bounds
},
completion: { (finished) in
transitionContext.completeTransition(true)
})
İşte tüm hızlı dosyanın bir özeti:
https://gist.github.com/alanzeino/603293f9da5cd0b7f6b60dc20bc766be