App Store Animasyonları
App Store’un “Today” kısmında yer alan animasyonları, UIViewPropertyAnimator sayesinde kendi uygulamalarınıza kolaylıkla ekleyebilirsiniz!
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. 🎉
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.
- 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.
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. 😊
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.
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.
İkinci UILabel elemanımız ise alt başlığı temsil edecek ve kodda captionLabel
olarak tanımlanacak.
Üçüncü ve son UILabel elemanımız ise gövde metnini temsil edecek ve kodda descriptionLabel
olarak tanımlanacak.
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.
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.
Ş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.
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ı).
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ı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.
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).
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.
Ö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! 💻