UIKit ve UIView ile Görünümlerde iOS Animasyonları Gerçekleştirme

Yayınlanan: 2022-03-10
Kısa özet ↬ Bu makale, iOS animasyonları hakkında, bunu yapmanın farklı yollarını kapsamlı bir şekilde kapsayan bir başlangıç ​​noktası olmayı amaçlamaktadır. Animasyonların temellerini anlayarak başlıyoruz, sunulan farklı yöntemleri kullanarak tek bir örnek oluşturan Çekirdek Çerçevelere geçiyoruz ve son olarak performansı ayarlamanın yollarını arıyoruz.

On 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.

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Ç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:

  1. 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.
  2. Animasyonun son halini temsil etmesi gereken butonun yeni karesini ayarladık.
  3. 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:

  1. duration
    Kod bloğunun ne kadar süreyle çalışması gerektiğini belirleyen animasyonun süresini temsil eder.
  2. delay
    Animasyon başlamadan önce sahip olmak istediğimiz ilk gecikmeyi temsil eder.
  3. 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.
  4. velocity
    Animasyonun başlaması gereken hızı temsil eder.
  5. options
    Görünüm animasyonunuza uygulamak istediğiniz animasyon eğrisi türü.
  6. 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:

  1. Süreyi ve animasyon eğrisini geçerek UIViewProperty API'sini çağırıyoruz.
  2. 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:

  1. duration
    Animasyonun süresini ileterek API'yi çağırın.
  2. delay
    Animasyonun ilk gecikme süresi.
  3. options
    Görünüm animasyonunuza uygulamak istediğiniz animasyon eğrisinin türü.
  4. animations
    Geliştirici/kullanıcı tarafından tasarlanan tüm ana kare animasyonlarını alan blok.
  5. 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.
  6. relativeStartTime
    Animasyon bloğu koleksiyonundaki animasyonun başlangıç ​​zamanını tanımlar.
  7. relativeDuration
    Bu belirli animasyonun genel süresini tanımlar.
  8. 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:

  1. begin
    Animasyon kod bloğunun başlangıcını temsil eder.
  2. duration
    Genel animasyon süresi.
  3. curve
    Animasyona uygulanması gereken zamanlama eğrisini temsil eder.
  4. UIView.animate
    Düğmenin çerçevesini değiştiren ilk animasyonumuz.
  5. CABasicAnimation
    Canlandırmak istediğimiz şey bu olduğundan, cornerRadius olarak başvurarak CABasicAnimation 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.
  6. fromValue
    Animasyonun başlangıç ​​değerini, yani animasyonun başlaması gereken düğmenin ilk cornerRadius değerini temsil eder.
  7. toValue
    Animasyonun son değerini, yani animasyonun bitmesi gereken düğmenin son cornerRadius değerini temsil eder.
  8. 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.
  9. addAnimation
    Animasyonun gerçekleştirilmesi gereken Keypath'i temsil ederek, tüm animasyon sürecinin konfigürasyonunu içeren animasyon nesnesini katmana ekleriz.
  10. 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:

  1. UIKitDynamicAnimator
    Animasyonları gerçekleştirmek için bir orkestratör görevi gören bir UIKitDynamicAnimator nesnesi oluşturduk. Butonumuzun denetimini de referans görünümü olarak geçtik.
  2. UIGravityBehavior
    Bir UIGravityBehavior nesnesi yarattık ve bu davranışın enjekte edildiği dizi elemanlarına butonumuzu ilettik.
  3. addBehavior
    Animatöre yerçekimi nesnesini ekledik.

    Bu, aşağıda gösterildiği gibi bir animasyon oluşturmalıdır:
    Düğmenin ekranın ortasından (orijinal konumundan) aşağıya ve ötesine nasıl düştüğüne dikkat edin.
    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
  4. UICollisionBehavior
    Bir UICollisionBehavior nesnesi yarattık ve davranışın öğeye eklenmesi için düğmeyi geçtik.
  5. 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.
  6. 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çin UIDynamicItemBehavior 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
  7. UIDynamicItemBehavior
    Bir UIDynamicItemBehavior nesnesi oluşturduk ve davranışın öğeye eklenmesi için düğmeyi ilettik.
  8. 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.
  9. 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!