App Store Animasyonları

App Store’un “Today” kısmında yer alan animasyonları, UIViewPropertyAnimator sayesinde kendi uygulamalarınıza kolaylıkla ekleyebilirsiniz!

Nadin Tamer
TurkishKit
7 min readMay 27, 2019

--

Hepinize merhabalar! 👋🏻 Yeni bir Swift yazısıyla karşınızdayız. Eminim ki hepiniz App Store uygulamasının “Today” kısmında yer alan animasyonları daha önce görmüşsünüzdür. Bugünkü makalemizde Swift dilini kullanarak buna benzer bir animasyon yaratmayı öğreneceğiz. 🎉

Yazının sonunda buna benzer bir animasyon yaratmış olacağız!

Başlamadan söylemiş olayım, eğer ARKit hakkındaki yeni yazımızı okumaya henüz fırsatınız olmadıysa okumanızı kesinlikle öneririm! 😉

UIViewPropertyAnimator Nedir?

Bahsettiğimiz animasyonu yaratmak için iOS 10 ile birlikte tanıtılan UIViewPropertyAnimator sınıfını kullanacağız. Bu sınıfla animasyonlar yaratmak için ilk olarak bir animator objesi tanımlayacak, sonraysa bu objenin üzerinde startAnimation() metodunu çağırarak animasyonu başlatacağız.

⚠️ Önemli: Her ne kadar bir animator objesi yaratmış olsak da, startAnimation() metodu çağrılana kadar herhangi bir animasyon olmayacaktır.

UIViewPropertyAnimator sınıfının temelde yaptığı şey, ona verilen başlangıç ve bitiş durumlarının arasındaki animasyonu oluşturmaktadır. Başlangıç durumu, elemanların startAnimation() metodunun çağrıldığı andaki konumları (veya başka özellikleri — örneğin renk) olarak kabul edilir. Animator objesi yaratılırken ise bir bitiş durumu tanımlanır. UIViewPropertyAnimator de bu iki durum arasındaki animasyonu oluşturur! 😁 Dolayısıyla bizim işimiz aslında sadece, başlangıç ve bitiş durumlarını belirlemek olacak.

Tabii ki UIViewPropertyAnimator sınıfının birçok farklı özelliği var, ancak biz bu yazımızda sadece dörty tanesini kullanacağımızdan onlara odaklanacağız. UIViewPropertyAnimator hakkında daha detaylı bilgi almak isterseniz her zamanki gibi Apple’ın dokümantasyonunu inceleyebilirsiniz. 😊

İlk olarak animator objemizi yaratırken vereceğimiz parametreleri inceleyelim:

  • duration: Animasyonun saniye biriminden süresini ifade eder. Bu sayı arttıkça animasyon yavaşlar, azaldıkça hızlanır.
  • dampingRatio: Animasyonun ne kadar pürüzsüz olduğunu ve ne kadar salındığını ifade eder ve 0 ila 1 arasında değerler alır. Bu sayı 0'a yaklaştıkça animasyon daha çok salınır/seker, 1'e yaklaştıkça ise daha pürüzsüz hale gelir ve salınmaz. Aynı animasyonun farklı dampingRatio değerleri ile bir karşılaştırmasını aşağıda görebilirsiniz.
Sol: dampingRatio = 0.8 | Sağ: dampingRatio = 0.2
  • isReversed: Animasyonun ters yöne akıp akmadığını ifade eder. true değerini aldığında animasyon bitiş durumundan başlangıç durumuna akar.
  • pausesOnCompletion: Animasyonun tamamlandığında hala aktif olup olmayacağını ifade eder. true değerini aldığında animasyon bittiğinde inaktif hale gelir.

Animasyonumuzu Kodlamaya Başlayalım!

UIViewPropertyAnimator sınıfının temellerini öğrendiğimize göre artık animasyonumuzu kodlayabiliriz! 💪🏻 Açtığımız Single View App Xcode projesinin Main.storyboard dosyasından, ekranımızı tasarlayarak başlayalım.

İlk olarak ekrana UILabel olarak bir başlık ve altına da bir UIView ekliyoruz.

Ekranımız şimdilik böyle gözüküyor.

Bu uygulamamızda yarattığımız arayüz elemanlarının konumları oldukça önemli olacağından aynı zamanda Size Inspector menüsünün de görüntülerini paylaşacağım. 😊

UIView elemanımızın konumu ve boyutu.

Her zaman olduğu gibi kntrl + sürükle metodunu kullanarak ViewController.swift dosyasına UIView elemanımız için bir outlet açıyoruz. Örnek uygulamada değişken ismi olarak cardView kullandım.

Şimdiyse yarattığımız UIView elemanının içerisine başka elemanlar eklemeye başlayacağız. İlk olarak bir UIImageView alıp UIView elemanımızın içerisine sürükleyelim ve boyutunu UIView ile aynı olacak şekilde ayarlayalım.

UIImageView elemanımızı UIView’nın içerisine ekledik.

Size Inspector menüsünü incelerseniz UIImageView elemanımızın konumunun x: 0, y: 0 olarak tanımlandığını göreceksiniz. Bunun sebebi, UIImageView elemanının konumunun içerisinde bulunduğu UIView’a göre tanımlanmasıdır.

Sonrasında Assets.xcassets klasörüne herhangi bir resmi sürükleyip bırakarak ve Attributes Inspector menüsünden Image seçeneğini değiştirerek UIImageView’nın içerisinde yer alan resmi ayarlayabilirsiniz. Ayrıca kntrl + sürükle yaparak UIImageView elemanını coverImageView olarak tanımlayacağız.

Artık ekranımıza biraz yazı eklemenin zamanı geldi! Toplam 3 tane UILabel elemanı ekleyeceğiz, ve bunların hepsi cardView ‘nın içerisinde yer alacak. İlk UILabel elemanımız başlığı temsil edecek ve kodda titleLabel olarak tanımlanacak.

titleLabel elemanının konumu ve boyutu.

İkinci UILabel elemanımız ise alt başlığı temsil edecek ve kodda captionLabel olarak tanımlanacak.

captionLabel elemanının konumu ve boyutu.

Üçüncü ve son UILabel elemanımız ise gövde metnini temsil edecek ve kodda descriptionLabel olarak tanımlanacak.

descriptionLabel elemanının konumu ve boyutu.

Artık ekran tasarımımız neredeyse bitti. Son olarak animasyonu kapatmak için sağ üst köşeye (yani cardView elemanının dışına) bir UIButton ekleyeceğiz. Bu UIButton elemanını da kodumuzda backButton olarak tanımlayacağız.

Tebrikler! Ekran tasarımımızı bitirdik, artık sadece kodlaması kaldı! Bu noktada kısa bir kontrol yapalım. Main.storyboard dosyasındaki ekranınız, yaklaşık olarak aşağıdakine benziyor olacaktır.

Ekran tasarımımızın son hali.

Kodunuzda ise tüm elemanları tanımladığınızı kontrol etmeyi unutmayın! Yaklaşık olarak aşağıdakine benzer bir kodunuz olmalıdır. İsterseniz değişken isimlerini farklı bir şekilde tanımlayabilirsiniz, ancak diğer tüm kodlarda da değiştirmeniz gerekecektir.

Tüm arayüz elemanlarımızı kodun içerisinde tanımladık.

Şimdi sıra geldi kodlamaya! 💻 İlk olarak viewDidLoad() metodumuzun içerisine birkaç satır daha ekleyerek ekranımızın başlangıç durumunu oluşturacağız.

viewDidLoad() metodumuz.

Haydi bu kodu daha yakından inceleyelim. İlk iki satırda cornerRadius özelliğini kullanarak fotoğrafımızın kenarlarının yuvarlanmasını sağlıyoruz. Sonraki satırda ise descriptionLabel elemanının alpha özelliğini 0'a eşitleyerek, şeffaf olmasını sağlıyoruz (çünkü uygulama ilk açıldığında bu yazının gözükmesini istemiyoruz). Benzer bir şekilde backButton elemanının da kenarlarını yuvarlak yapıyor ve şeffaf olmasını sağlıyoruz.

Şimdiye asıl animasyon koduna başlayabiliriz. Hatırlarsanız UIViewPropertyAnimator sınıfını kullanırken bir animator objesi yaratmamız gerektiğinden bahsetmiştik. Biz de şimdi bu objeyi aşağıdaki kodla ViewController sınıfımızın bir özelliği olarak tanımlayacağız (yani bu kodumuz class tanımının içinde, ama viewDidLoad() metodunun dışında yer almalı).

UIViewPropertyAnimator sınıfını kullanarak bir animator objesi yaratıyoruz.

Sakın gözünüz korkmasın! Bu oldukça uzun bir kod gibi gözükse de anlaması aslında oldukça basit. 🙂

İlk iki satırımızda screenHeight ve screenWidth değişkenlerini tanımlıyoruz ki ekranın boyutlarına kolayca ulaşabilelim. Sonraki satırda ise animator objemizi tanımlamaya başlıyoruz. Burada gördüğümüz duration ve dampingRatio argümanları, önceden konuştuğumuz özellikleri temsil ediyor. Animasyonumuz toplam 1.0 saniye sürecek ve dampingRatio özelliği 1'e yakın olduğundan oldukça pürüzsüz bir şekilde ilerleyecek.

animator tanımımızdan sonraki süslü parantezlerin içerisinde ise bitiş durumumuzu tanımlıyoruz, yani cardView ile coverImageView elemanlarını büyütüyor, titleLabel ile captionLabel elemanlarının konumuyla oynuyor, ve descriptionLabel ile backButton elemanlarını görünür hale getiriyoruz. Aslında yaptığımız şey, ekranı yeniden tasarlamak. Güncel ekrandan tasarladığımız bu yeni ekrana geçiş yapmak ise UIViewPropertyAnimator’ın görevi olacak.

Bu kodda kafanıza takılabilecek bir nokta ise lazy var tanımını kullanmamız. Bu tanım, temelde objemizin değerinin ilk defa yaratıldığı andan ziyade, ilk defa kod içerisinde kullanıldığında hesaplanması anlamına gelir. Bu genelde uzun işlemlerde gereksiz işlem gücü kullanmamak için kullanılır, ancak bizim uygulamamızda durum biraz farklı. Fark ederseniz animator objemizi ViewController sınıfının bir özelliği olarak tanımladık. Dolayısıyla her yeni bir ViewController yaratıldığında, bu animator objesi de yaratılacak. Ancak fark ederseniz animator objesi, ViewController sınıfının başka özelliklerine de bağlı (örneğin backButton). Bu özellikler ise ViewController’ın oluşumu bitmeden tanımlı olmayacak! Bu noktada bir paradoksa giriyoruz: animator objesini tanımlamadan ViewController tamamlanmamış olacak, ancak ViewController tamamlanmadan animator objesini tanımlayamıyoruz. 🤔 Bu sorunu işte lazy var tanımını kullanarak çözüyoruz. Daha animator objesini kullanmadığımızdan, değeri hesaplanmıyor ve sorunsuz bir şekilde ViewController’ımızı yaratmış oluyoruz. animator objesinin değeri ise onu daha sonra bir metodda çağırdımızda hesaplanacak. 👍🏻

Şimdiyse animator objesiyle alakalı olarak bir satırımız daha olacak, onu da viewDidLoad() metodunun içerisine ekleyeceğiz.

Bu satır, uygulamamızın çalışması için çok önemli!

Bu satırın amacı, animasyonumuzun bittiğinde inaktif hale geçmesini sağlamaktır, çünkü animasyon bittiğinde (ters yöne akması için) yönünü değiştireceğiz ve bu değişikliği sadece inaktif haldeyken yapabiliyoruz.

Artık sadece son birkaç kod satırımız kaldı! Library menüsünden bir UITapGestureRecognizer alıp coverImageView içerisine sürüklüyoruz. Bunu daha sonra soldaki Document Outline kısmından Tap Gesture Recognizer’ın üzerine sağ tıklayarak kontrol edebilirsiniz: Referencing Outlet Collections kısmında Cover Image View yazmalı.

Sonrasında kntrl + sürükle yaparak ViewController.swift dosyasında bir Action oluşturuyoruz. Örnek uygulamada bu metoda tapped ismini verdim.

tapped metodumuz, animasyonu başlatıyor.

Bu metod sayesinde kullanıcı coverImageView kısmına tıkladığında, animasyonumuz başlayacak. Dikkat ederseniz ilk satırda isReversed özelliğini false olarak tanımlayarak animasyonun başlangıçtan bitişe doğru akacağını belirttik.

Son olarak animasyondan sonra açılan ekranı kapatmak için bir koda ihtiyacımız var. Burada yapacağımız tek şey, animasyonu ters yönde (yani bitişten başlangıca doğru) akıtmak olacak. Bunun için backButton elemanından kntrl + sürükle yaparak yeniden bir Action oluşturmak (buna backButtonTapped ismini verdik).

backButtonTapped metodumuz, animasyonun ters yöne akmasını sağlıyor.

Bu metodda ise isReversed özelliğini true olarak tanımlayarak, animasyonun ters yöne akacağını belirttik.

İşte uygulamamız bitti! 🎉 Tıpkı App Store’dakine benzeyen bir animasyon yaratmayı başardık.

Uygulamamızın son hali!

Örnek uygulamayı kendiniz denemek istiyorsanız kaynak kodları GitHub üzerinden indirebilirsiniz:

Artık App Store’un “Today” kısmındaki animasyonların nasıl kodlandığını öğrenmiş bulunuyoruz. Siz de bu gibi ve benzeri animasyonları kolaylıkla uygulamalarınıza ekleyip, uygulamanızın arayüzünü daha pürüzsüz ve sezgisel hale getirebilirsiniz. Keyifli kodlamalar! 💻

--

--