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 UINavigationController
menjiwai antara dua pengontrol tampilan jika Anda membuat subkelas UINavigationController
dan mengembalikan turunan kelas yang sesuai dengan UIViewControllerAnimatedTransitioning
protokol.
Sebagai contoh di sini adalah UINavigationController
subclass 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 UINavigationControllerDelegate
sendiri, dan dalam ekstensi pada subkelas saya, saya menerapkan metode UINavigationControllerDelegate
yang 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 NavigationControllerAnimation
instance melalui inisialisasi. Saya melakukan ini sehingga dalam NavigationControllerAnimation
implementasi UIViewControllerAnimatedTransitioning
protokol 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 UIViewControllerAnimatedTransitioning
protokol 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, to
view controller harus ditambahkan sebagai subview dari containerView
dalam konteks transisi.
Ketika animasi Anda selesai, Anda harus menelepon transitionContext.completeTransition(true)
. Jika Anda melakukan transisi interaktif, Anda harus mengembalikan Bool
ke 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 toViewController
tampilan asal pada layar x-axis off, menambahkannya sebagai subview dari containerView
, menggerakkannya ke layar dengan mengatur origin.x
ke nol. Pada saat yang sama, saya menghidupkan fromViewController
tampilan itu dengan origin.x
mematikannya:
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 toViewController
sebagai subview dari containerView
, dan hidupkan fromViewController
ke kanan saat Anda menghidupkan toViewController
dari 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