Kisah one view controller yang ingin pamer dengan baik

Sekali waktu ada pengontrol tampilan sederhana VCYellow . Dan dia tidak memiliki gambar, atau teks, atau bahkan logika bisnis kecil. Dia menjalani kehidupan pengontrol pandangan yang biasa.


Teman sesama pengontrol tampilan VCMain terkadang menyajikannya kepada dunia:


class VCMain: UIViewController { ... @IBAction func onBtnTapMeTapped(_ sender: Any) { let vcYellow = self.storyboard!.instantiateViewController(withIdentifier: "VCYellow") as! VCYellow self.present(vcYellow, animated: true, completion: nil) } 

Dan VCYellow, pada gilirannya, bersembunyi dengan bantuan satu tombol "X", yang ia sangat bangga dengan:


 class VCYellow: UIViewController { ... @IBAction func onBtnCloseTapped(_ sender: Any) { self.dismiss(animated: true, completion: nil) } 

Dan itu terlihat tidak terlalu buruk, tetapi membosankan dan biasa saja:



Tetapi pahlawan kita memiliki mimpi untuk belajar menunjukkan dan bersembunyi dalam keindahan. Ya, sehingga Anda dapat mengubah keindahan ini di kemudian hari di liburan atau hanya untuk menghormati suasana hati yang baik.



Tahun-tahun berlalu ... dan mimpi itu akan tetap menjadi mimpi seandainya VCYellow tidak belajar tentang sihir yang disebut:


 UIViewControllerTransitioningDelegate 

Dan kekuatan sihir ini terletak pada kenyataan bahwa memungkinkan untuk menyelipkan animator yang tepat untuk menunjukkan dan menyembunyikan pengontrol tampilan. Apa yang diimpikan oleh pengontrol kami.
Dia membaca di gulungan kuno bagaimana menggunakan mantra dan mulai mempersiapkan.
Saya menulis buaian dengan mantra itu sendiri agar tidak lupa:


 extension VCYellow: UIViewControllerTransitioningDelegate { func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return AnimatorPresent(startFrame: self.startFrame) } func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return AnimatorDismiss(endFrame: self.startFrame) } } 

Di dalamnya, ia dengan hati-hati melukis bahwa untuk pertunjukan Anda harus menggunakan animator Animator Present , dan ketika menutup AnimatorDismiss .
Nah, sebagai bantuan untuk kedua animator, diputuskan untuk mentransfer bingkai tombol utama dari VCMain


Dan kemudian dia sendiri disetel secara mental. Karena tanpa sikap yang benar, seperti yang Anda tahu, tidak ada keajaiban yang bekerja:


 override func viewDidLoad() { super.viewDidLoad() self.modalPresentationStyle = .custom self.transitioningDelegate = self } 

Dia meminta temannya, VCM, untuk mempresentasikan dirinya untuk memeriksa bagaimana sihir itu bekerja dan ... itu tidak berhasil ...
Ternyata AnimatorPresent dan AnimatorDismiss tidak muncul sendiri.


Sudah terlambat untuk berhenti, dan pahlawan kita memutuskan untuk membuat animator yang diperlukan. Saya mencari-cari di bagian yang diperlukan dari gulungan kuno dan menemukan dua hal yang cukup untuk membuat animator.


Pertama, Anda perlu mengatur waktu yang diberikan untuk animasi:


 func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.3 } 

dan kedua menunjukkan animasi itu sendiri:


 func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { //1 guard let vcTo = transitionContext.viewController(forKey: .to), let snapshot = vcTo.view.snapshotView(afterScreenUpdates: true) else { return } //2 let vContainer = transitionContext.containerView //3 vcTo.view.isHidden = true vContainer.addSubview(vcTo.view) //4 snapshot.frame = self.startFrame vContainer.addSubview(snapshot) UIView.animate(withDuration: 0.3, animations: { //5 snapshot.frame = (transitionContext.finalFrame(for: vcTo)) }, completion: { success in //6 vcTo.view.isHidden = false snapshot.removeFromSuperview() transitionContext.completeTransition(true) }) } 

  1. Tarik keluar view controller yang disajikan (dalam kasus kami VCYellow) dan ambil gambarnya. Foto diperlukan untuk menyederhanakan animasi.
  2. Dapatkan tampilan tentang sihir animasi yang akan berlangsung. Sebut saja konteksnya.
  3. Kaitkan pandangan pengendali akhir pada konteks dan sembunyikan. Tampilkan
  4. diputuskan setelah animasi berakhir.
  5. Siapkan foto untuk animasi. Kurangi ke ukuran awal dan lemparkan pada konteks.
  6. Membagi foto menjadi layar penuh, sehingga menggerakkan proses presentasi.
  7. Setelah animasi selesai, tunjukkan tampilan nyata pengendali akhir,
  8. singkirkan foto dan laporkan bahwa tindakan telah selesai.

Akibatnya, ada animator untuk ditampilkan:


 import UIKit class AnimatorPresent: NSObject, UIViewControllerAnimatedTransitioning { let startFrame: CGRect init(startFrame: CGRect) { self.startFrame = startFrame } func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.3 } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let vcTo = transitionContext.viewController(forKey: .to), let snapshot = vcTo.view.snapshotView(afterScreenUpdates: true) else { return } let vContainer = transitionContext.containerView vcTo.view.isHidden = true vContainer.addSubview(vcTo.view) snapshot.frame = self.startFrame vContainer.addSubview(snapshot) UIView.animate(withDuration: 0.3, animations: { snapshot.frame = (transitionContext.finalFrame(for: vcTo)) }, completion: { success in vcTo.view.isHidden = false snapshot.removeFromSuperview() transitionContext.completeTransition(true) }) } } 

Dan setelah itu tidak sulit untuk menulis animator untuk bersembunyi, yang melakukan hal yang sama, tetapi sebaliknya:


 import UIKit class AnimatorDismiss: NSObject, UIViewControllerAnimatedTransitioning { let endFrame: CGRect init(endFrame: CGRect) { self.endFrame = endFrame } func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.3 } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let vcTo = transitionContext.viewController(forKey: .to), let vcFrom = transitionContext.viewController(forKey: .from), let snapshot = vcFrom.view.snapshotView(afterScreenUpdates: true) else { return } let vContainer = transitionContext.containerView vContainer.addSubview(vcTo.view) vContainer.addSubview(snapshot) vcFrom.view.isHidden = true UIView.animate(withDuration: 0.3, animations: { snapshot.frame = self.endFrame }, completion: { success in transitionContext.completeTransition(true) }) } } 

Setelah menyelesaikan semua sentuhan akhir, VCYellow kembali meminta temannya, VCMain, untuk menampilkan dirinya sendiri dan lihat!



Keajaiban itu berhasil! Mimpi VCYellow menjadi kenyataan! Sekarang dia dapat menunjukkan dan bersembunyi sesukanya dan tidak ada yang akan membatasi imajinasinya!


Contoh proyek dapat diunduh di sini.


Artikel yang saya gunakan untuk inspirasi ada di sini.

Source: https://habr.com/ru/post/id424853/


All Articles