Karena ini adalah hasil teratas di Google, saya pikir saya akan membagikan apa yang menurut saya cara paling waras; yang menggunakan API transisi iOS 7+. Saya menerapkan ini untuk iOS 10 dengan Swift 3.
Sangat mudah untuk menggabungkan ini dengan bagaimana UINavigationControllermenjiwai antara dua pengontrol tampilan jika Anda membuat subkelas UINavigationControllerdan mengembalikan turunan kelas yang sesuai dengan UIViewControllerAnimatedTransitioningprotokol.
Sebagai contoh di sini adalah UINavigationControllersubclass saya :
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)
}
}
Anda dapat melihat bahwa saya mengaturnya UINavigationControllerDelegatesendiri, dan dalam ekstensi pada subkelas saya, saya menerapkan metode UINavigationControllerDelegateyang memungkinkan Anda mengembalikan pengontrol animasi khusus (yaitu, NavigationControllerAnimation). Pengontrol animasi khusus ini akan menggantikan animasi stok untuk Anda.
Anda mungkin bertanya-tanya mengapa saya melewatkan operasi ke NavigationControllerAnimationinstance melalui inisialisasi. Saya melakukan ini sehingga dalam NavigationControllerAnimationimplementasi UIViewControllerAnimatedTransitioningprotokol saya tahu apa operasi itu (yaitu, 'push' atau 'pop'). Ini membantu untuk mengetahui jenis animasi apa yang harus saya lakukan. Sebagian besar waktu, Anda ingin melakukan animasi yang berbeda tergantung pada operasinya.
Sisanya cukup standar. Terapkan dua fungsi yang diperlukan dalam UIViewControllerAnimatedTransitioningprotokol dan hidupkan sesuka Anda:
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
}
}
}
Penting untuk diingat, bahwa untuk setiap jenis operasi yang berbeda (yaitu, 'push' atau 'pop), pengontrol dari dan ke tampilan akan berbeda. Ketika Anda berada dalam operasi push, controller untuk melihat akan menjadi yang didorong. Saat Anda berada dalam operasi pop, to view controller akan menjadi salah satu yang sedang ditransisikan ke, dan controller dari view akan menjadi yang muncul.
Juga, toview controller harus ditambahkan sebagai subview dari containerViewdalam konteks transisi.
Ketika animasi Anda selesai, Anda harus menelepon transitionContext.completeTransition(true) . Jika Anda melakukan transisi interaktif, Anda harus mengembalikan Boolke completeTransition(didComplete: Bool), secara dinamis , tergantung pada apakah transisi selesai pada akhir animasi.
Akhirnya ( bacaan opsional ), Anda mungkin ingin melihat bagaimana saya melakukan transisi yang sedang saya kerjakan. Kode ini sedikit lebih peretasan dan saya menulisnya dengan cepat sehingga saya tidak akan mengatakan itu kode animasi yang bagus tetapi masih menunjukkan bagaimana melakukan bagian animasi.
Milik saya adalah transisi yang sangat sederhana; Saya ingin meniru animasi yang sama dengan yang biasanya dilakukan UINavigationController, tetapi alih-alih animasi 'halaman berikutnya di atas', saya ingin menerapkan animasi 1: 1 dari pengontrol tampilan lama pada saat yang sama dengan tampilan baru pengontrol muncul. Ini memiliki efek membuat dua pengendali tampilan tampak seolah-olah mereka disematkan satu sama lain.
Untuk operasi push, yang pertama-tama mengharuskan pengaturan toViewControllertampilan asal pada layar x-axis off, menambahkannya sebagai subview dari containerView, menggerakkannya ke layar dengan mengatur origin.xke nol. Pada saat yang sama, saya menghidupkan fromViewControllertampilan itu dengan origin.xmematikannya:
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)
})
Operasi pop pada dasarnya adalah kebalikannya. Tambahkan toViewControllersebagai subview dari containerView, dan hidupkan fromViewControllerke kanan saat Anda menghidupkan toViewControllerdari kiri:
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)
})
Inilah inti dengan seluruh file cepat:
https://gist.github.com/alanzeino/603293f9da5cd0b7f6b60dc20bc766be