UIKit ve UIView ile Görünümlerde iOS Animasyonları Gerçekleştirme
Yayınlanan: 2022-03-10On yıldan fazla bir süredir iOS geliştiricisiyim ve iOS'ta animasyon gerçekleştirmenin tüm olası yollarını birleştiren makaleleri nadiren gördüm. Bu makale, aynı şeyi yapmanın farklı yollarını kapsamlı bir şekilde ele almak amacıyla iOS animasyonları hakkında bir başlangıç olmayı amaçlamaktadır.
Konunun kapsamı göz önüne alındığında, her bölümü kısa ve öz bir şekilde oldukça yüksek bir düzeyde ele alacağız. Amaç, okuyucuyu iOS uygulamasına animasyonlar eklemek için bir dizi seçenekle eğitmektir.
iOS ile ilgili konulara başlamadan önce animasyon hızına kısaca bir göz atalım.
60FPS'de Animasyon
Genellikle videolarda, her kare bir görüntü ile temsil edilir ve kare hızı, sırayla çevrilen görüntülerin sayısını belirler. Bu, 'saniyedeki kare sayısı' veya FPS olarak adlandırılır.
FPS, bir saniye içinde çevrilen durağan görüntü sayısını belirler; bu, kelimenin tam anlamıyla, görüntü/kare sayısı ne kadar fazlaysa, videoda daha fazla ayrıntı/bilgi görüntüleneceği anlamına gelir. Bu, animasyonlar için de geçerlidir.
FPS genellikle animasyonların kalitesini belirlemek için kullanılır. Herhangi bir iyi animasyonun 60 fps veya daha yüksek hızda çalışması gerektiğine dair yaygın bir görüş vardır - 60 fps'den düşük herhangi bir şey biraz kapalı hissettirir.
30FPS ve 60FPS arasındaki farkı görmek ister misiniz? Şunu bir kontrol et!
Farkı fark ettiniz mi? İnsan gözü, titreşimi kesinlikle daha düşük fps'de hissedebilir. Bu nedenle, oluşturduğunuz herhangi bir animasyonun 60FPS veya daha yüksek hızda koşma temel kuralına uyduğundan emin olmak her zaman iyi bir uygulamadır. Bu daha gerçekçi ve canlı hissettirir.
FPS'ye baktıktan sonra, şimdi bize animasyonlar gerçekleştirmenin bir yolunu sağlayan farklı temel iOS çerçevelerini inceleyelim.
Çekirdek Çerçeveler
Bu bölümde, görünüm animasyonları oluşturmak için kullanılabilecek iOS SDK'daki çerçevelere değineceğiz. İlgili bir örnekle özellik setlerini açıklayarak her birini hızlı bir şekilde inceleyeceğiz.
UIKit/ UIView Animasyonları
UIView, iOS uygulamalarında içerik görüntüleyen herhangi bir görünüm için temel sınıftır.
Bize UIView sağlayan çerçeve olan UIKit, geliştiricilerin daha az yaparak daha fazlasını elde etmesini kolaylaştıran bazı temel animasyon işlevlerini zaten sağlıyor.
API, UIView.animate
, herhangi bir görünümün özellikleri blok tabanlı sözdiziminde özellik değerleri sağlanarak kolayca canlandırılabildiğinden, görünümleri canlandırmanın en kolay yoludur.
UIKit animasyonlarında, yalnızca UIVIew'in canlandırılabilir özelliklerinin değiştirilmesi önerilir, aksi takdirde animasyonların görünümün beklenmedik bir durumda sonlanmasına neden olabileceği yansımalar olacaktır.
animasyon(withDuration: animasyonlar: tamamlama)
Bu yöntem, bir dizi görünümün canlandırılması gereken canlandırılabilir özellik değişiklikleri olan animasyon süresini alır. Tamamlama bloğu, animasyon gerçekleştirilerek görünüm tamamlandığında bir geri arama sağlar.
Bu tek API ile bir görünümde hareket etme, ölçekleme, döndürme, solma vb. gibi hemen hemen her türlü animasyon elde edilebilir.
Şimdi, bir düğme boyutu değişikliğini canlandırmak istediğinizi veya belirli bir görünümün ekrana yakınlaştırılmasını istediğinizi düşünün. UIView.animate
API'sini kullanarak bunu şu şekilde yapabiliriz:
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 }
İşte burada yaptığımız şey:
- Blok içinde açıklanan animasyonun ne kadar süreyle çalışması gerektiğini gösteren, kendisine geçirilen bir süre değeriyle
UIView.animate
yöntemini çağırırız. - Animasyonun son halini temsil etmesi gereken butonun yeni karesini ayarladık.
- Düğme
center
, denetim merkeziyle birlikte ekranın ortasında kalacak şekilde ayarladık.
Yukarıdaki animasyon kodu bloğu, mevcut kareden değişen düğme karesinin animasyonunu tetiklemelidir:
Width = 0, Height = 0
Son kareye:
Width = Height = newButtonWidth
Ve işte animasyon şöyle görünecek:
animateWithDuration
Bu yöntem, önceki API'de gerçekleştirebildiğiniz her şeyi, görünüm animasyonlarına eklenen bazı fizik davranışlarıyla yapabileceğiniz, animate yönteminin bir uzantısı gibidir.
Örneğin, yukarıda yaptığımız animasyonda yay sönümleme efektleri elde etmek istiyorsanız, kod şu şekilde görünecektir:
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)
İşte kullandığımız parametre seti:
-
duration
Kod bloğunun ne kadar süreyle çalışması gerektiğini belirleyen animasyonun süresini temsil eder. -
delay
Animasyon başlamadan önce sahip olmak istediğimiz ilk gecikmeyi temsil eder. -
SpringWithDamping
Görünümün davranmasını istediğimiz yaylı efektin değerini temsil eder. Değer 0 ile 1 arasında olmalıdır. Değer ne kadar düşükse, yay salınımı o kadar yüksek olur. -
velocity
Animasyonun başlaması gereken hızı temsil eder. -
options
Görünüm animasyonunuza uygulamak istediğiniz animasyon eğrisi türü. - Son olarak, hareketli olması gereken düğmenin çerçevesini ayarladığımız kod bloğu. Önceki animasyonla aynı.
Ve yukarıdaki animasyon yapılandırmasıyla animasyon şu şekilde görünür:
UIViewPropertyAnimatör
Animasyonlar üzerinde biraz daha fazla kontrol için, UIViewPropertyAnimator
, animasyonları duraklatmak ve devam ettirmek için bize bir yol sağladığında kullanışlı oluyor. Özel zamanlamaya sahip olabilir ve animasyonunuzun etkileşimli ve kesintiye uğramasını sağlayabilirsiniz. Bu, kullanıcı eylemleriyle de etkileşime girebilen animasyonlar gerçekleştirirken çok yararlıdır.
Klasik 'Kilidi Açmak için Kaydır' hareketi ve oynatıcı görünümü animasyonu kapat/genişlet (Müzik uygulamasında) etkileşimli ve kesintiye uğrayabilir animasyonların örnekleridir. Parmağınızla bir görünümü hareket ettirmeye başlayabilir, ardından bırakabilirsiniz; görünüm orijinal konumuna geri dönecektir. Alternatif olarak, animasyon sırasında görüntüyü yakalayabilir ve parmağınızla sürüklemeye devam edebilirsiniz.
Aşağıda, UIViewPropertyAnimator
kullanarak animasyonu nasıl elde edebileceğimize dair basit bir örnek verilmiştir:
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
İşte yaptığımız şey:
- Süreyi ve animasyon eğrisini geçerek
UIViewProperty
API'sini çağırıyoruz. - Yukarıdaki UIView.animate API'lerinin her ikisinden farklı olarak, siz kendiniz belirtmedikçe animasyon başlamaz, yani tüm animasyon sürecinin/akışının tam kontrolü sizdedir.
Şimdi, animasyonlar üzerinde daha da fazla kontrol sahibi olmak istediğinizi varsayalım. Örneğin, animasyondaki her kareyi tasarlamak ve kontrol etmek istiyorsunuz. Bunun için başka bir API var, animateKeyframes
. Ama onu derinlemesine incelemeden önce, bir animasyonda karenin ne olduğuna hızlıca bakalım.
frame
Nedir?
Başlangıç durumundan son duruma kadar görünümün çerçeve değişikliklerinin/geçişlerinin bir koleksiyonu animation
olarak tanımlanır ve görünümün animasyon sırasındaki her bir konumu bir frame
olarak adlandırılır.
canlandırmakAnahtar kareler
Bu API, animasyonu, farklı zamanlamalar ve geçişlerle birden çok animasyon tanımlayabileceğiniz şekilde tasarlamanın bir yolunu sağlar. Bunu yayınlayın, API tüm animasyonları tek bir kusursuz deneyime entegre eder.
Diyelim ki ekrandaki butonumuzu rastgele bir şekilde hareket ettirmek istiyoruz. Bunu yapmak için ana kare animasyon API'sini nasıl kullanabileceğimizi görelim.
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 } })
İşte dağılım:
-
duration
Animasyonun süresini ileterek API'yi çağırın. -
delay
Animasyonun ilk gecikme süresi. -
options
Görünüm animasyonunuza uygulamak istediğiniz animasyon eğrisinin türü. -
animations
Geliştirici/kullanıcı tarafından tasarlanan tüm ana kare animasyonlarını alan blok. -
addKeyFrame
Her bir animasyonu tasarlamak için API'yi arayın. Bizim durumumuzda, düğmenin her hareketini tanımladık. Bloğuna eklenen, ihtiyacımız olduğu kadar çok animasyona sahip olabiliriz. -
relativeStartTime
Animasyon bloğu koleksiyonundaki animasyonun başlangıç zamanını tanımlar. -
relativeDuration
Bu belirli animasyonun genel süresini tanımlar. -
center
Bizim durumumuzda, düğmeyi ekran etrafında hareket ettirmek için düğmenin merkez özelliğini değiştiriyoruz.
Ve son animasyonlar şöyle görünüyor:
ÇekirdekAnimasyon
Herhangi bir UIKit tabanlı animasyon, dahili olarak çekirdek animasyonlara çevrilir. Böylece, Core Animation çerçevesi, herhangi bir UIKit animasyonu için bir destek katmanı veya omurga görevi görür. Bu nedenle, tüm UIKit animasyon API'leri, kolayca tüketilebilir veya uygun bir şekilde çekirdek animasyon API'lerinin kapsüllenmiş katmanlarından başka bir şey değildir.
UIKit animasyon API'leri, çoğunlukla görünümün canlandırılabilir özellikleri için kullanıldığından, bir görünüm üzerinde gerçekleştirilen animasyonlar üzerinde fazla kontrol sağlamaz. Bu nedenle, animasyonun her karesi üzerinde kontrol sahibi olmayı düşündüğünüz bu gibi durumlarda, doğrudan temel animasyon API'lerini kullanmak daha iyidir. Alternatif olarak, hem UIView animasyonları hem de temel animasyonlar birlikte de kullanılabilir.
UIView + Çekirdek Animasyon
UIView ve Core Animation API'lerini kullanarak zamanlama eğrisini belirterek aynı düğme değiştirme animasyonunu nasıl yeniden oluşturabileceğimizi görelim.
Animasyon eğrisini belirlemenizi ve kontrol etmenizi sağlayan CATransaction
zamanlama işlevlerini kullanabiliriz.
CATransaction
zamanlama işlevini ve UIView animasyonlarının bir kombinasyonunu kullanan köşe yarıçapı ile bir düğme boyutu değiştirme animasyonu örneğine bakalım:
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
İşte dağılım:
-
begin
Animasyon kod bloğunun başlangıcını temsil eder. -
duration
Genel animasyon süresi. -
curve
Animasyona uygulanması gereken zamanlama eğrisini temsil eder. -
UIView.animate
Düğmenin çerçevesini değiştiren ilk animasyonumuz. -
CABasicAnimation
Canlandırmak istediğimiz şey bu olduğundan,cornerRadius
olarak başvurarakCABasicAnimation
nesnesini yaratırız. Benzer şekilde, ana kare animasyonları üzerinde ayrıntılı düzeyde kontrol sahibi olmak istiyorsanız,CAKeyframeAnimation
sınıfını kullanabilirsiniz. -
fromValue
Animasyonun başlangıç değerini, yani animasyonun başlaması gereken düğmenin ilkcornerRadius
değerini temsil eder. -
toValue
Animasyonun son değerini, yani animasyonun bitmesi gereken düğmenin soncornerRadius
değerini temsil eder. -
cornerRadius
cornerRadius
özelliğini animasyonun son değeriyle ayarlamalıyız, aksi takdirde düğmenin cornerRadius değeri, animasyon tamamlandıktan sonra otomatik olarak ilk değerine döndürülür. -
addAnimation
Animasyonun gerçekleştirilmesi gereken Keypath'i temsil ederek, tüm animasyon sürecinin konfigürasyonunu içeren animasyon nesnesini katmana ekleriz. -
commit
Animasyon kod bloğunun sonunu temsil eder ve animasyonu başlatır.
Son animasyon şu şekilde görünecektir:
Bu blog, her adımda size yol gösteren talimatlarla birlikte Core Animation çerçeve API'lerinin çoğunda sizi düzgün bir şekilde yönlendirdiği için daha gelişmiş animasyonlar oluşturmaya yardımcı olmak için harika bir okumadır.
UIKitDynamics
UIKit Dynamics, UIKit kontrollerine çarpışma, yerçekimi, itme, yakalama vb. herhangi bir fizik davranışını eklemenizi sağlayan UIKit için fizik motorudur.
UIKitDinamikAnimatör
Bu, herhangi bir UI denetimi tarafından tetiklenen tüm animasyonları düzenleyen UIKit Dynamics çerçevesinin yönetici sınıfıdır.
UIKitDinamik Davranış
Bir animatöre herhangi bir fizik davranışı eklemenizi ve ardından ona bağlı görünümde gerçekleştirmesini sağlar.
UIKitDynamics için farklı davranış türleri şunları içerir:
-
UIAttachmentBehavior
-
UICollisionBehavior
-
UIFieldBehavior
-
UIGravityBehavior
-
UIPushBehavior
-
UISnapBehavior
UIKitDynamics'in mimarisi şuna benzer. 1'den 5'e kadar olan Maddelerin tek bir görünümle değiştirilebileceğini unutmayın.
Düğmemize biraz fizik davranışı uygulayalım. Düğmeye yerçekiminin nasıl uygulanacağını göreceğiz, böylece bize gerçek bir nesneyle uğraşıyormuş hissi verecek.
var dynamicAnimator : UIDynamicAnimator! var gravityBehavior : UIGravityBehavior! dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1 gravityBehavior = UIGravityBehavior(items: [button]) //2 dynamicAnimator.addBehavior(gravityBehavior) //3
İşte dağılım:
-
UIKitDynamicAnimator
Animasyonları gerçekleştirmek için bir orkestratör görevi gören birUIKitDynamicAnimator
nesnesi oluşturduk. Butonumuzun denetimini de referans görünümü olarak geçtik. -
UIGravityBehavior
BirUIGravityBehavior
nesnesi yarattık ve bu davranışın enjekte edildiği dizi elemanlarına butonumuzu ilettik. -
addBehavior
Animatöre yerçekimi nesnesini ekledik.
Bu, aşağıda gösterildiği gibi bir animasyon oluşturmalıdır:
Animatöre ekranın altını zemin olarak kabul etmesini söylemeliyiz.UICollisionBehavior
resme girdiği yer burasıdır.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
BirUICollisionBehavior
nesnesi yarattık ve davranışın öğeye eklenmesi için düğmeyi geçtik. -
translatesReferenceBoundsIntoBoundary
Bu özelliğin etkinleştirilmesi, animatöre, bizim durumumuzda ekranın alt kısmı olan referans görünümler sınırını son olarak almasını söyler. -
addBehavior
Burada animatöre çarpışma davranışı ekledik.
Şimdi, düğmemiz yere çarpmalı ve aşağıda gösterildiği gibi hareketsiz durmalıdır:
Bu çok güzel, değil mi?
Şimdi, nesnemizin daha gerçek hissetmesi için bir sıçrama efekti eklemeyi deneyelim. Bunu yapmak içinUIDynamicItemBehavior
sınıfını kullanacağız.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
BirUIDynamicItemBehavior
nesnesi oluşturduk ve davranışın öğeye eklenmesi için düğmeyi ilettik. -
elasticity
Değer 0-1 arasında olmalıdır, esnekliği temsil eder, yani cismin çarptığında zeminde kaç kez zıplaması gerektiğini gösterir. Sihrin gerçekleştiği yer burasıdır - bu özelliği değiştirerek toplar, şişeler, sert nesneler vb. gibi farklı türdeki nesneleri ayırt edebilirsiniz. -
addBehavior
Burada animatöre çarpışma davranışı ekledik.
Şimdi, düğmemiz yere çarptığında aşağıda gösterildiği gibi zıplamalıdır:
Bu depo oldukça faydalıdır ve tüm UIKitDynamics davranışlarını çalışırken gösterir. Ayrıca, her davranışla oynamak için kaynak kodu sağlar. Bu, bence, görünümlerde iOS animasyonları gerçekleştirmenin kapsamlı bir yol listesi olarak hizmet etmelidir!
Bir sonraki bölümde, animasyonların performansını ölçmemize yardımcı olacak araçlara kısaca göz atacağız. Ayrıca, geliştirme sürenizden büyük ölçüde tasarruf edeceğinden, Xcode yapınızı optimize etmenin yollarına bakmanızı da tavsiye ederim.
Performans Ayarı
Bu bölümde, iOS animasyonlarının performansını ölçmenin ve ayarlamanın yollarına bakacağız. Bir iOS geliştiricisi olarak, genel uygulamanın performansını ölçmek için Bellek Sızıntıları ve Tahsisler gibi Xcode Araçlarını zaten kullanmış olabilirsiniz. Benzer şekilde, animasyonların performansını ölçmek için kullanılabilecek araçlar vardır.
Core Animation
Enstrümanı
Core Animation
aracını deneyin ve uygulama ekranınızın sunduğu FPS'yi görebilmeniz gerekir. Bu, iOS uygulamanızda oluşturulan herhangi bir animasyonun performansını/hızını ölçmenin harika bir yoludur.
Resim çizme
Gölgeler gibi efektlere sahip resimler gibi ağır içerikleri görüntüleyen uygulamada FPS büyük ölçüde düşürülür. Bu gibi durumlarda, Görüntüyü doğrudan UIImageView
'ın görüntü özelliğine atamak yerine, Core Graphics API'lerini kullanarak görüntüyü bir bağlamda ayrı olarak çizmeyi deneyin. Bu, ana iş parçacığı yerine ayrı bir iş parçacığında yapıldığında görüntü açma mantığını eşzamansız olarak gerçekleştirerek görüntü görüntüleme süresini aşırı derecede azaltır.
rasterleştirme
Rasterleştirme, karmaşık katman bilgilerini önbelleğe almak için kullanılan bir işlemdir, böylece bu görünümler oluşturulduklarında yeniden çizilmez. Görünümlerin yeniden çizilmesi, FPS'deki azalmanın ana nedenidir ve bu nedenle, birkaç kez yeniden kullanılacak görünümlere rasterleştirme uygulamak en iyisidir.
Toplama
Sonuç olarak, iOS animasyonları için faydalı kaynakların bir listesini de özetledim. iOS animasyonları üzerinde çalışırken bunu çok kullanışlı bulabilirsiniz. Ek olarak, bu tasarım araçları setini, animasyonlara dalmadan önce bir (tasarım) adımı olarak yararlı bulabilirsiniz.
Umarım iOS animasyonlarını çevreleyen mümkün olduğunca çok konuyu ele alabilmişimdir. Bu yazıda kaçırmış olabileceğim bir şey varsa, lütfen aşağıdaki yorumlar bölümünde bana bildirin, ekleme yapmaktan memnuniyet duyarım!