SwiftUI: NavigationView

NavigationView elemanı ile uygulamanızın navigasyonunu basit bir şekilde sağlayabilirsiniz.

Sinan Ulusan
TurkishKit
8 min readJan 11, 2021

--

Bir uygulamanın navigasyonunun sağlanmasında, istenilen bilgilerin gösterilmesinde ve aksiyon alımında NavigationView elemanı bir uygulama için önemli UI elemanıdır. Bu yazımızda, NavigationView elemanını kullanmayı öğreneceğiz. Hazırsanız hiç vakit kaybetmeden başlayalım. 🤟🏻

NavigationView Oluşturma

İlk olarak yeni bir Xcode projesi oluşturalım. Projemiz tabii ki bir SwiftUI projesi olacak. Projemizi oluşturduktan sonra Xcode’un bizim için varsayılan olarak verdiği kodlardan Text elemanını ve padding “modifier”ını silelim. Sonrasında body içerisine NavigationView elemanını oluşturalım.

Ardından NavigationView elemanı içerisine bir VStack oluşturduktan sonra içerisine bu kodları ekleyelim:

Burada ne yaptık? Sistem resimlerinden “music.quarternote.3” adında olan resmi kullandık. resizable() “modifier”ını kullanarak yeniden boyutlandırma iznini verdik. Resmin en-boy oranını düzgün bir hale getirmek için aspectRatio değerimizi .fit olarak ayarladık. frame “modifier”ı ile resmimizin genişliğini ve yüksekliği 100 olarak ayarladık, hizasının ortalanması için alignment özelliğini .center olarak tanımladık.

VStack elemanımızı kapattıktan sonra NavigationView elemanına bir başlık eklemek için navigationBarTitle “modifier”ını yazalım: Başlık “Müzik” olsun. displayMod özelliğini .inline olarak ayarlayalım. Girdiğimiz kodlar sonrasında uygulamamızın son hali bu şekilde olacaktır.👇🏻

Ardından body içerisindeki padding “modifier”ının altına gelerek aşağıdaki kodları yazalım.

Burada ne yaptık? Resmimizin alına Text ekledik ve font “modifier”ı ile yazımızın görüşünü değiştirdik. Ardından NavigationLink elemanını ve görüşünüşünü değiştirmek için dört tane “modifier” kullandık.

NavigationLink Nedir?

NavigationLink, kullanıcının bir butona tıkladığı zaman yeni bir sayfaya geçiş yapmasını sağlayan arayüz elemanıdır.

Artık “Preview” ekranından uygulamamızın son halini görebiliriz.

Şimdi ise NavigationView elemanında butonları nasıl kullanabileceğimizi öğrenelim.

NavigationView Elemanına Bar Buttonları Ekleme

NavigationView elemanı aracılığı ile sayfalar arasında gezinmek ve ekstra aksiyonlar alabilmek için NavigationBarItem elemanlarına ihtiyacımız vardır.)

Bu elemanlara örnek olarak Apple’ın “Takvim” ve “Anımsatıcılar” uygulaması verilebilir.

Fark edeceğiniz üzere, az önce oluşturduğumuz butona tıkladıktan sonra ortaya çıkan ekranda tıpkı “Anımsatıcılar” uygulamasındaki gibi bir -geri- butonu vardı. Şimdi oluşturacağımız NavigationView elemanları ise daha çok “Takvim” uygulamasının sağ tarafındaki gibi olacaklar.

İlk önce A elemanlarını eklemek için navigationBarItems “modifier”ını yazalım.

Hem sağa hem de sola iki buton koyacağımız için “leading” ve “trailing” özellikerini yazdık: Bu özelliklerin içerisine iki tane buton yazalım.

Bu butonlara tıkladığımızda belli aksiyonlar alabilmek için belli değerleri değiştirmemiz gerekiyor. Bu butonlara tıklayınca olmasını istediğimiz aksiyon yeni -sheet- ekranların ortaya çıkması olduğu için iki farklı Bool türünden değer tanımlayalım.

Bu değerler true değerini aldığı zaman istediğimiz ekranın ortaya çıkmasını sağlamak için bu değerlerin true değeri alması gerekiyor. Bu aksiyon da tam olarak butonlara tıklandığı zaman olacağı için butonların action özelliklerinde bu iki değeri de true değerine eşitliyoruz.

Şimdi uygulamayı çalıştırdığımızda uygulamamız aşağıdaki görsel gibi olacaktır, ama şu an butonlara tıkladığımızda yaptığımız değişiklikler arayüze yansımıyor. Az önce bu butonların yeni bir sayfaya geçiş yapmak için kullanılacağını söylemiştik. Bunun olabilmesi için sheet “modifier”ına ihtiyacımız var: Onun sayesinde butonlara bastığımızda ortaya çıkacak ekranların kart görünümünde olmasında sağlayabiliyoruz. Uygulamanızda yapacağınız işlemlere göre bu şekilde yeni bir ekran çıkartmanız kullanıcı deneyimini iyi yönde etkileyebilir. Bu yüzden sheet “modifier”ını genellikle kullanırız.

Sheet

Bu “modifier”ın çalışabilmesi için en büyük kapsama alanına sahip elemanın -Burada o NavigationView oluyor- sonunda yazmamız gerekiyor.

Artık NavigationBarItem elemanlarından birine bastığımız zaman yukarıdaki Text elemanı ortaya çıkacaktır, çünkü o butonlara basılarak ancak showSheet değerini değiştirebiliyoruz.

Text yerine gerçek bir ekranı ortaya çıkartabilmek için yeni bir “SwiftUI View” dosyası oluşturalım. Burada yaptığımız uygulama küçücük bir uygulama olduğu için bu sayfada da uygulamaya uyan birkaç içerik serpiştirdim.

Her iki butonun da farklı ekranları açması için üstteki yeni bir “SwiftUI View” dosyası daha oluşturalım.

Aynı ekranın içerisinden iki farklı “sheet” ekranı çıkartmak için SwiftUI’da biraz dolanmamız gerekecek çünkü bizim sheet “modifier”ına bir tane çıktı değer vermemiz gerekecek. Bunu verebilmek için de belli bir değere göre bu iki View elemanımızdan birini seçmemiz gerekecek. Bunun için “SheetNavigator” adında bir sınıf oluşturalım. Bu sınıf sayesinde hangi ekranın açılıp hangisinin açılmayacağını kaydedeceğiz.

“SheetNavigator” sınıfımızı “ContentView” elemanında tutmak için bu şekilde tanımlamalıyız.

Hangi butona tıklandığı zaman hangi ekranın ortaya çıkacağını belirtmek için aşağıdaki gibi navigationBarItems “modifier”ını değiştirelim.

Artık sheet “modifier”ını değiştirebiliriz. Aslında yapacağımız tek şey bir if yapısı ile sheetNavigatior özelliğinin içerisindeki değerlere göre ekran göstermesini sağlamak.

Son olarak, “sheet” ekranlarından kullanıcıların nasıl geri dönebileceklerini kodlamaya geldi.

Normalde “sheet” olmayan ekranlarda, makalenin başında olduğu gördüğünüz gibi, yeni bir ekrana gidildiği zaman geri gitme butonları oluşur ama “sheet” ekranlarda bu böyle olmuyor. Onun yerine “sheet” ekranlardan kaydırarak veya butona basarak kaldırabiliyoruz. Şu ana kadar yaptığımız “sheet” ekranlarını da sadece kaydırarak kaldırabilirsiniz. Bu çoğu uygulama için pek de iyi bir kullanıcı deneyimi oluşturmaz. Genellikle kullanıcılar “sheet” ekranlardan çıkmak için bir butona tıklamayı tercih ederler. Yani “sheet” ekranlarımız için birer “Vazgeç” butonuna ihtiyacımız var. Bu butonları NavigationBarItem olarak tanımlayabiliriz.

İlk önce “FirstView” elemanına bir buton tanımlayalım aynı aşağıdaki gibi.

Ekranımızı kaldırmak için SwiftUI’ın bize sunmuş olduğu bir elemanı kullanacağız: presentationMode. Hemen onu “FirstView” içerisinde tanımalayalım.

Sonrasında az önce oluşturduğumuz butonun action özelliğine presentationMode elemanının dismiss() metodunu çağıralım.

“FirstView” ekranımızın artık tamamen hazır! Sıra “SecondSheetView” ekranında. Şimdiden söyleyeyim, o birazcık daha uzun sürecek. 😋

Bazı durumlarda uygulamanızda kullandığınız bir “sheet” ekranının kullanıcının istediği gibi kaldırabilmesini istemeyebilirsiniz. Örneğin, biz de “SecondSheetView” için bunu istiyoruz: Kullanıcı “SecondSheetView”dan çıkabilmek için yapabileceği tek şey az önce oluşturduğumuz gibi bir “Vazgeç” butonu olsun ve başka türlü o ekrandan çıkamasın, yani kaydırma işlemi yaparak ekrandan çıkamasın. Bunu yapabilmek için ekstra elemanlara ihtiyacımız olacak çünkü normalde SwiftUI bu yapacağımız işi kendi içerisinde barındırmıyor.

SwiftUI’da yapamadığımız ama UIKit’te yapabildiğimiz neredeyse bütün özellikleri SwiftUI’da da yapabilmemizi sağlayan UIViewControllerRepresentable yardımıyla “ModelView” adında bir sınıf oluşturalım.

Bu sınıf, bir ekranın kaydırılabilir olup olmayacağını tanımlamamızı sağlayacak. Bunun için temel üç tane özelliğe ihtiyacımız var.

view özelliği sınıfımızın cenerik bir sınıf olmasını sağlamak içindir. isModel ise View elemanının kaydırabilir olup olmadığını belirlememize yarar. onDismissalAttempt ise bir opsiyonel Void elemanıdır. Onun sayesinde bu söylediğimiz aksiyonları alabileceğiz.

SwiftUI elemanlarını UIKit elemanlarına çevirmek için kullanılan UIHostingController ile “ModelView” sınıfının çıktısını alıyoruz denilebilir.

Geri kalanlar ise “ModalView” sınıfının temel olarak çalışabilmesini sağlamak içindir.

Şimdi bu sınıfı bir View metodunun içerisinde kullanacağız. Bunun için aşağıdaki View “extension”ınını oluşturalım.

Sonrasında “presentation” adında bir metod tanımlayalım. Metodun çıktısı “some View” olduğu için bu metod ile bir arayüz elemanı oluşturabiliyoruz.

Bu metodu kullanmadan önce “SecondSheetView” elemanın içerisinde @Binding operatörü ile bir Bool değeri tanımlayalım.

Bu değer sayesinde objeler arasında veri alışverişi yapabileceğiz.

@Binding Nedir?

@Binding bir özelliği doğrudan veri depolamak yerine başka bir yerde saklanan bir veri kaynağına bağlayan bir property wrapper ifadesidir. @Binding ile alakalı daha fazla bilgi için aşağıdaki yazımızı okuyabilirsiniz:

“SecondSheetView” için de bir “Vazgeç” NavigationBarItem elemanı oluşturalım ve action özelliğinde showSheet değerini false olarak ayarlayalım.

Bu sayede “Vazgeç” butonuna basınca ekran ortadan kaybolacak.

Şu an Xcode’dan hata mesajı alıyor olmasınız çünkü “ContentView” içerisinde kullandığınız “SecondSheetView” elemanı sizden showSheet özelliğini tanımlamanızı isteyecektir. Hatayı düzeltmek için “SecondSheetView” elemanını aşağıdaki gibi değiştirmeliyiz.

Uygulamamız neredeyse bitti sayılır. “SecondSheetView” elemanının kaydırılamaz olmasını sağlamak için tek yapmamız gereken üstteki “SecondSheetView” elemanında presentation metodunu kullanmaktır.

Artık projemizi çalıştırıp uygulamamızı deneyimleyebiliriz!

Bu yazımızda yapmış olduğumuz projemize buradan ulaşabilirsiniz:

https://github.com/TurkishKit/SwiftUI-NavigationView

Apple SwiftUI’ı tanıttığı ilk sene SwiftUI’da özellikle uygulama navigasyonu ile alakalı gerçekten büyük problemler vardı. Bu makaleden de görebileceğimiz üzere artık SwiftUI’da bu konu ile alakalı pek bir sorun yaşamıyoruz.

Umarım sizler için faydalı bir yazı olmuştur. Bir sonraki yazımızda görüşmek üzere! 🤠

Yazı Önerisi 👀

NavigationView elemanı aslında UINavigationBar elemanının başka bir versiyonudur: UINavigationBar bir UIKit elemanıdır. UINavigationBar ile alakalı daha fazla bilgi öğrenmek için aşağıdaki makalemizi okuyabilirsiniz.

Bizi daha yakından takip etmek istiyorsanız, sosyal medya hesaplarımıza aşağıdan ulaşabilirsiniz!

Twitter | Instagram | Facebook

--

--