Melakukan Animasi iOS Pada Tampilan Dengan UIKit Dan UIView
Diterbitkan: 2022-03-10Saya telah menjadi pengembang iOS selama lebih dari satu dekade sekarang dan jarang melihat artikel yang menggabungkan semua cara yang mungkin untuk melakukan animasi di iOS. Artikel ini bertujuan untuk menjadi primer pada animasi iOS dengan maksud mencakup secara mendalam berbagai cara untuk melakukan hal yang sama.
Mengingat luasnya topik, kami akan membahas setiap bagian secara ringkas pada tingkat yang cukup tinggi. Tujuannya adalah untuk mengedukasi pembaca dengan serangkaian pilihan untuk menambahkan animasi ke aplikasi iOS-nya.
Sebelum kita mulai dengan topik yang terkait dengan iOS, mari kita lihat sekilas tentang kecepatan animasi.
Menganimasikan Pada 60FPS
Umumnya dalam video, setiap frame diwakili oleh sebuah gambar dan frame rate menentukan jumlah gambar yang dibalik secara berurutan. Ini disebut sebagai 'frame per detik' atau FPS.
FPS menentukan jumlah gambar diam yang dibalik dalam satu detik, yang secara harfiah berarti bahwa semakin banyak jumlah gambar/bingkai, semakin banyak detail/informasi yang ditampilkan dalam video. Ini juga berlaku untuk animasi.
FPS biasanya digunakan untuk menentukan kualitas animasi. Ada pendapat umum bahwa setiap animasi yang bagus harus berjalan pada 60fps atau lebih tinggi — apa pun yang kurang dari 60fps akan terasa kurang pas.
Apakah Anda ingin melihat perbedaan antara 30FPS dan 60FPS? Periksa ini!
Apakah Anda memperhatikan perbedaannya? Mata manusia pasti bisa merasakan jitter pada fps yang lebih rendah. Oleh karena itu, selalu praktik yang baik untuk memastikan bahwa setiap animasi yang Anda buat, mematuhi aturan dasar berjalan pada 60FPS atau lebih tinggi. Ini membuatnya terasa lebih realistis dan hidup.
Setelah melihat FPS, sekarang mari kita selidiki kerangka kerja inti iOS yang berbeda yang memberi kita cara untuk melakukan animasi.
Kerangka Inti
Di bagian ini, kita akan menyentuh kerangka kerja di SDK iOS yang dapat digunakan untuk membuat animasi tampilan. Kami akan melakukan penelusuran singkat melalui masing-masing dari mereka, menjelaskan set fitur mereka dengan contoh yang relevan.
Animasi UIKit/ UIView
UIView adalah kelas dasar untuk tampilan apa pun yang menampilkan konten di aplikasi iOS.
UIKit, kerangka kerja yang memberi kita UIView, sudah memberi kita beberapa fungsi animasi dasar yang memudahkan pengembang untuk mencapai lebih banyak dengan melakukan lebih sedikit.
API, UIView.animate
, adalah cara termudah untuk menganimasikan tampilan karena properti tampilan apa pun dapat dengan mudah dianimasikan dengan memberikan nilai properti dalam sintaks berbasis blok.
Dalam animasi UIKit, disarankan untuk hanya memodifikasi properti animasi UIVIew, jika tidak, akan ada dampak di mana animasi dapat menyebabkan tampilan berakhir dalam keadaan yang tidak terduga.
animasi (denganDurasi: animasi: selesai)
Metode ini mengambil durasi animasi, satu set perubahan properti animasi tampilan yang perlu dianimasikan. Blok penyelesaian memberikan panggilan balik ketika tampilan selesai dengan melakukan animasi.
Hampir semua jenis animasi seperti bergerak, menskalakan, memutar, memudar, dll. pada tampilan dapat dicapai dengan API tunggal ini.
Sekarang, pertimbangkan bahwa Anda ingin menganimasikan perubahan ukuran tombol atau Anda ingin tampilan tertentu memperbesar layar. Ini adalah bagaimana kita dapat melakukannya menggunakan API UIView.animate
:
let newButtonWidth: CGFloat = 60 UIView.animate(withDuration: 2.0) { //1 self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth) //2 self.button.center = self.view.center //3 }
Inilah yang kami lakukan di sini:
- Kami memanggil metode
UIView.animate
dengan nilai durasi yang diteruskan ke sana yang menunjukkan berapa lama animasi, yang dijelaskan di dalam blok, harus berjalan. - Kami mengatur bingkai tombol baru yang harus mewakili keadaan akhir animasi.
- Kami mengatur pusat tombol dengan
center
superview-nya sehingga tetap berada di tengah layar.
Blok kode animasi di atas harus memicu animasi bingkai tombol yang berubah dari bingkai saat ini:
Width = 0, Height = 0
Ke bingkai terakhir:
Width = Height = newButtonWidth
Dan inilah tampilan animasinya:
animasiDenganDurasi
Metode ini seperti perpanjangan dari metode animate di mana Anda dapat melakukan semua yang dapat Anda lakukan di API sebelumnya dengan beberapa perilaku fisika yang ditambahkan ke animasi tampilan.
Misalnya, jika Anda ingin mendapatkan efek redaman pegas dalam animasi yang telah kita lakukan di atas, maka seperti inilah tampilan kodenya:
let newButtonWidth: CGFloat = 60 UIView.animate(withDuration: 1.0, //1 delay: 0.0, //2 usingSpringWithDamping: 0.3, //3 initialSpringVelocity: 1, //4 options: UIView.AnimationOptions.curveEaseInOut, //5 animations: ({ //6 self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth) self.button.center = self.view.center }), completion: nil)
Berikut set parameter yang kami gunakan:
-
duration
Mewakili durasi animasi yang menentukan berapa lama blok kode harus dijalankan. -
delay
Mewakili penundaan awal yang ingin kita miliki sebelum animasi dimulai. -
SpringWithDamping
Mewakili nilai efek kenyal yang kita inginkan agar tampilan berperilaku. Nilainya harus antara 0 hingga 1. Semakin rendah nilainya, semakin tinggi osilasi pegas. -
velocity
Merupakan kecepatan di mana animasi harus dimulai. -
options
Jenis kurva animasi yang ingin Anda terapkan ke animasi tampilan Anda. - Terakhir, blok kode tempat kita mengatur bingkai tombol yang perlu dianimasikan. Sama seperti animasi sebelumnya.
Dan inilah tampilan animasi dengan konfigurasi animasi di atas:
UIViewPropertyAnimator
Untuk sedikit lebih mengontrol animasi, UIViewPropertyAnimator
berguna di mana ia memberi kita cara untuk menjeda dan melanjutkan animasi. Anda dapat memiliki pengaturan waktu khusus dan membuat animasi Anda menjadi interaktif dan dapat diinterupsi. Ini sangat membantu saat melakukan animasi yang juga dapat berinteraksi dengan tindakan pengguna.
Gerakan klasik 'Geser untuk Membuka Kunci' dan tampilan pemutar mengabaikan/memperluas animasi (dalam aplikasi Musik) adalah contoh animasi interaktif dan dapat diinterupsi. Anda dapat mulai memindahkan tampilan dengan jari Anda, lalu melepaskannya dan tampilan akan kembali ke posisi semula. Atau, Anda dapat menangkap tampilan selama animasi dan terus menyeretnya dengan jari Anda.
Berikut adalah contoh sederhana bagaimana kita bisa mencapai animasi menggunakan UIViewPropertyAnimator
:
let newButtonWidth: CGFloat = 60 let animator = UIViewPropertyAnimator(duration:0.3, curve: .linear) { //1 self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth) self.button.center = self.view.center } animator.startAnimation() //2
Inilah yang kami lakukan:
- Kami memanggil
UIViewProperty
API dengan melewatkan durasi dan kurva animasi. - Tidak seperti kedua API UIView.animate di atas, animasi tidak akan dimulai kecuali Anda menentukannya sendiri, yaitu Anda memegang kendali penuh atas proses/alur animasi lengkap.
Sekarang, katakanlah Anda ingin lebih mengontrol animasi. Misalnya, Anda ingin mendesain dan mengontrol setiap frame dalam animasi. Ada API lain untuk itu, animateKeyframes
. Tapi sebelum kita mempelajarinya, mari kita lihat dulu apa itu frame, dalam sebuah animasi.
Apa itu frame
?
Kumpulan perubahan/transisi bingkai tampilan, dari status awal ke status akhir, didefinisikan sebagai animation
dan setiap posisi tampilan selama animasi disebut sebagai frame
.
animateKeyframes
API ini menyediakan cara untuk mendesain animasi sedemikian rupa sehingga Anda dapat menentukan beberapa animasi dengan pengaturan waktu dan transisi yang berbeda. Posting ini, API hanya mengintegrasikan semua animasi menjadi satu pengalaman yang mulus.
Katakanlah kita ingin memindahkan tombol kita di layar secara acak. Mari kita lihat bagaimana kita dapat menggunakan API animasi keyframe untuk melakukannya.
UIView.animateKeyframes(withDuration: 5, //1 delay: 0, //2 options: .calculationModeLinear, //3 animations: { //4 UIView.addKeyframe( //5 withRelativeStartTime: 0.25, //6 relativeDuration: 0.25) { //7 self.button.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.maxY) //8 } UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.25) { self.button.center = CGPoint(x: self.view.bounds.width, y: start.y) } UIView.addKeyframe(withRelativeStartTime: 0.75, relativeDuration: 0.25) { self.button.center = start } })
Berikut rinciannya:
-
duration
Panggil API dengan meneruskan durasi animasi. -
delay
Durasi penundaan awal animasi. -
options
Jenis kurva animasi yang ingin Anda terapkan ke animasi tampilan Anda. -
animations
Blok yang mengambil semua animasi keyframe yang dirancang oleh pengembang/pengguna. -
addKeyFrame
Panggil API untuk mendesain setiap animasi. Dalam kasus kami, kami telah mendefinisikan setiap gerakan tombol. Kita dapat memiliki animasi sebanyak yang kita butuhkan, ditambahkan ke blok. -
relativeStartTime
Menentukan waktu mulai animasi dalam kumpulan blok animasi. -
relativeDuration
Menentukan durasi keseluruhan animasi khusus ini. -
center
Dalam kasus kami, kami cukup mengubah properti tengah tombol untuk memindahkan tombol di sekitar layar.
Dan seperti inilah tampilan animasi terakhir:
IntiAnimation
Setiap animasi berbasis UIKit diterjemahkan secara internal ke dalam animasi inti. Dengan demikian, kerangka Animasi Inti bertindak sebagai lapisan pendukung atau tulang punggung untuk setiap animasi UIKit. Oleh karena itu, semua API animasi UIKit tidak lain adalah lapisan yang dienkapsulasi dari API animasi inti dengan cara yang mudah dikonsumsi atau nyaman.
API animasi UIKit tidak memberikan banyak kontrol atas animasi yang telah dilakukan pada tampilan karena sebagian besar digunakan untuk properti tampilan yang dapat dianimasikan. Oleh karena itu dalam kasus seperti itu, di mana Anda bermaksud untuk memiliki kontrol atas setiap frame animasi, lebih baik menggunakan API animasi inti yang mendasarinya secara langsung. Atau, baik animasi UIView dan animasi inti dapat digunakan bersama juga.
UIView + Animasi Inti
Mari kita lihat bagaimana kita dapat membuat ulang animasi perubahan tombol yang sama bersama dengan menentukan kurva waktu menggunakan UIView dan Core Animation API.
Kita dapat menggunakan fungsi pengaturan waktu CATransaction
, yang memungkinkan Anda menentukan dan mengontrol kurva animasi.
Mari kita lihat contoh animasi perubahan ukuran tombol dengan radius sudutnya menggunakan fungsi pengaturan waktu CATransaction
dan kombinasi animasi UIView:
let oldValue = button.frame.width/2 let newButtonWidth: CGFloat = 60 /* Do Animations */ CATransaction.begin() //1 CATransaction.setAnimationDuration(2.0) //2 CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)) //3 // View animations //4 UIView.animate(withDuration: 1.0) { self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth) self.button.center = self.view.center } // Layer animations let cornerAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.cornerRadius)) //5 cornerAnimation.fromValue = oldValue //6 cornerAnimation.toValue = newButtonWidth/2 //7 button.layer.cornerRadius = newButtonWidth/2 //8 button.layer.add(cornerAnimation, forKey: #keyPath(CALayer.cornerRadius)) //9 CATransaction.commit() //10
Berikut rinciannya:
-
begin
Merupakan awal dari blok kode animasi. -
duration
Durasi animasi keseluruhan. -
curve
Mewakili kurva waktu yang perlu diterapkan pada animasi. -
UIView.animate
Animasi pertama kami untuk mengubah bingkai tombol. -
CABasicAnimation
Kami membuat objekCABasicAnimation
dengan merujukcornerRadius
tombol sebagai keypath karena itulah yang ingin kami animasikan. Demikian pula, jika Anda ingin memiliki kontrol level granular atas animasi keyframe, maka Anda dapat menggunakan kelasCAKeyframeAnimation
. -
fromValue
Mewakili nilai awal animasi, yaitu nilaicornerRadius
awal tombol dari mana animasi harus dimulai. -
toValue
Merupakan nilai akhir dari animasi, yaitu nilaicornerRadius
akhir dari tombol dimana animasi harus diakhiri. -
cornerRadius
Kita harus menyetel properticornerRadius
dari tombol dengan nilai akhir animasi, jika tidak, nilai cornerRadius tombol akan otomatis dikembalikan ke nilai awalnya setelah animasi selesai. -
addAnimation
Kami melampirkan objek animasi yang berisi konfigurasi seluruh proses animasi ke lapisan dengan mewakili Keypath yang animasinya perlu dilakukan. -
commit
Merupakan akhir dari blok kode animasi dan memulai animasi.
Ini adalah bagaimana animasi akhir akan terlihat seperti:
Blog ini adalah bacaan yang bagus untuk membantu membuat animasi yang lebih canggih karena dengan rapi memandu Anda melalui sebagian besar API kerangka Animasi Inti dengan instruksi yang memandu Anda melalui setiap langkah.
UIKitDynamics
UIKit Dynamics adalah mesin fisika untuk UIKit yang memungkinkan Anda untuk menambahkan perilaku fisika seperti tumbukan, gravitasi, dorong, jepret, dll, ke kontrol UIKit.
UIKitDynamicAnimator
Ini adalah kelas admin dari kerangka UIKit Dynamics yang mengatur semua animasi yang dipicu oleh kontrol UI yang diberikan.
UIKitDynamicBehavior
Ini memungkinkan Anda untuk menambahkan perilaku fisika apa pun ke animator yang kemudian memungkinkannya untuk tampil pada tampilan yang menyertainya.
Berbagai jenis perilaku untuk UIKitDynamics meliputi:
-
UIAttachmentBehavior
-
UICollisionBehavior
-
UIFieldBehavior
-
UIGravityBehavior
-
UIPushBehavior
-
UISnapBehavior
Arsitektur UIKitDynamics terlihat seperti ini. Perhatikan bahwa Item 1 hingga 5 dapat diganti dengan satu tampilan.
Mari kita terapkan beberapa perilaku fisika ke tombol kita. Kita akan melihat bagaimana menerapkan gravitasi ke tombol sehingga memberi kita perasaan berurusan dengan objek nyata.
var dynamicAnimator : UIDynamicAnimator! var gravityBehavior : UIGravityBehavior! dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1 gravityBehavior = UIGravityBehavior(items: [button]) //2 dynamicAnimator.addBehavior(gravityBehavior) //3
Berikut rinciannya:
-
UIKitDynamicAnimator
Kami telah membuat objekUIKitDynamicAnimator
yang bertindak sebagai orkestra untuk melakukan animasi. Kami juga telah melewati superview tombol kami sebagai tampilan referensi. -
UIGravityBehavior
Kami telah membuat objekUIGravityBehavior
dan meneruskan tombol kami ke elemen array tempat perilaku ini disuntikkan. -
addBehavior
Kami telah menambahkan objek gravitasi ke animator.
Ini harus membuat animasi seperti yang ditunjukkan di bawah ini:
Kita harus memberitahu animator untuk menganggap bagian bawah layar sebagai tanah. Di sinilahUICollisionBehavior
muncul.var dynamicAnimator : UIDynamicAnimator! var gravityBehavior : UIGravityBehavior! var collisionBehavior : UICollisionBehavior! dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1 gravityBehavior = UIGravityBehavior(items: [button]) //2 dynamicAnimator.addBehavior(gravityBehavior) //3 collisionBehavior = UICollisionBehavior(items: [button]) //4 collisionBehavior.translatesReferenceBoundsIntoBoundary = true //5 dynamicAnimator.addBehavior(collisionBehavior) //6
-
UICollisionBehavior
Kami telah membuat objekUICollisionBehavior
dan meneruskan tombol sehingga perilaku ditambahkan ke elemen. -
translatesReferenceBoundsIntoBoundary
Mengaktifkan properti ini memberi tahu animator untuk mengambil batas tampilan referensi sebagai akhir, yang merupakan bagian bawah layar dalam kasus kami. -
addBehavior
Kami telah menambahkan perilaku tabrakan ke animator di sini.
Sekarang, tombol kita harus menyentuh tanah dan berdiri diam seperti yang ditunjukkan di bawah ini:
Itu cukup rapi, bukan?
Sekarang, mari kita coba menambahkan efek pantulan agar objek kita terasa lebih nyata. Untuk melakukan itu, kita akan menggunakan kelasUIDynamicItemBehavior
.var dynamicAnimator : UIDynamicAnimator! var gravityBehavior : UIGravityBehavior! var collisionBehavior : UICollisionBehavior! var bouncingBehavior : UIDynamicItemBehavior! dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1 gravityBehavior = UIGravityBehavior(items: [button]) //2 dynamicAnimator.addBehavior(gravityBehavior) //3 collisionBehavior = UICollisionBehavior(items: [button]) //4 collisionBehavior.translatesReferenceBoundsIntoBoundary = true //5 dynamicAnimator.addBehavior(collisionBehavior) //6 //Adding the bounce effect bouncingBehavior = UIDynamicItemBehavior(items: [button]) //7 bouncingBehavior.elasticity = 0.75 //8 dynamicAnimator.addBehavior(bouncingBehavior) //9
-
UIDynamicItemBehavior
Kami telah membuat objekUIDynamicItemBehavior
dan meneruskan tombol sehingga perilaku ditambahkan ke elemen. -
elasticity
Nilai harus antara 0-1, itu mewakili elastisitas yaitu berapa kali benda harus memantul ke atas dan ke bawah tanah ketika dipukul. Di sinilah keajaiban terjadi — dengan mengutak-atik properti ini, Anda dapat membedakan berbagai jenis objek seperti bola, botol, benda keras, dan sebagainya. -
addBehavior
Kami telah menambahkan perilaku tabrakan ke animator di sini.
Sekarang, tombol kita harus memantul ketika menyentuh tanah seperti yang ditunjukkan di bawah ini:
Repo ini cukup membantu dan menunjukkan semua perilaku UIKitDynamics dalam tindakan. Ini juga menyediakan kode sumber untuk bermain-main dengan setiap perilaku. Itu, menurut saya, harus berfungsi sebagai daftar ekstensif cara untuk melakukan animasi iOS pada tampilan!
Di bagian selanjutnya, kita akan melihat sekilas alat yang akan membantu kita mengukur kinerja animasi. Saya juga merekomendasikan Anda untuk mencari cara untuk mengoptimalkan build Xcode Anda karena ini akan menghemat banyak waktu pengembangan Anda.
Penyesuaian Kinerja
Di bagian ini, kita akan melihat cara untuk mengukur dan menyetel kinerja animasi iOS. Sebagai pengembang iOS, Anda mungkin telah menggunakan Instrumen Xcode seperti Kebocoran Memori dan Alokasi untuk mengukur kinerja aplikasi secara keseluruhan. Demikian pula, ada instrumen yang dapat digunakan untuk mengukur kinerja animasi.
Instrumen Core Animation
Coba instrumen Core Animation
dan Anda akan dapat melihat FPS yang ditampilkan oleh layar aplikasi Anda. Ini adalah cara yang bagus untuk mengukur kinerja/kecepatan animasi apa pun yang dirender di aplikasi iOS Anda.
Menggambar
FPS sangat diturunkan di aplikasi yang menampilkan konten berat seperti gambar dengan efek seperti bayangan. Dalam kasus seperti itu, alih-alih menetapkan Gambar secara langsung ke properti gambar UIImageView
, cobalah menggambar gambar secara terpisah dalam konteks menggunakan Core Graphics API. Ini terlalu mengurangi waktu tampilan gambar dengan melakukan logika dekompresi gambar secara asinkron ketika dilakukan di utas terpisah, bukan di utas utama.
Rasterisasi
Rasterisasi adalah proses yang digunakan untuk menyimpan informasi lapisan kompleks sehingga tampilan ini tidak digambar ulang setiap kali dirender. Penggambaran ulang tampilan adalah penyebab utama penurunan FPS dan karenanya, yang terbaik adalah menerapkan rasterisasi pada tampilan yang akan digunakan kembali beberapa kali.
Membungkus
Sebagai penutup, saya juga telah merangkum daftar sumber daya yang berguna untuk animasi iOS. Anda mungkin merasa ini sangat berguna saat mengerjakan animasi iOS. Selain itu, Anda juga dapat menemukan seperangkat alat desain ini sebagai langkah (desain) sebelum mempelajari animasi.
Saya harap saya dapat membahas sebanyak mungkin topik seputar animasi iOS. Jika ada sesuatu yang saya lewatkan dalam artikel ini, beri tahu saya di bagian komentar di bawah dan saya akan dengan senang hati menambahkannya!