Flutter’da Sayfalar Arası Geçişler

Zeki ÇIPLAK
Flutter Türkiye
Published in
7 min readJul 18, 2019

--

Sayfalar Arası Geçiş

Flutter’da tek sayfa tasarımını yapmak kadar, oluşturulan çoklu sayfalar arasındaki geçişi sağlamak da önemlidir. Bazen bir sayfadan diğerine geçerken, önceki sayfaya geri dönülmesini istemeyebiliriz ya da bir sayfada kullanıcıdan edindiğimiz bir bilgiyi, başka bir sayfada kullanmak isteyebiliriz.

Bu makalede sizlere Flutter’da sayfalar arası geçişlerin nasıl yapıldığıyla ilgili ayrıntıları aktaracağım. Basit olanından, ayrıntılı olanına doğru bir yolculuğa çıkacağız.

1) Navigator.push & MaterialPageRoute & Navigator.pop

İlk olarak sayfalar arası geçişler için Navigator sınıfını kullanacağız. Bu amaçla üç sayfalı bir örneği incelemekle başlayacağız. Şimdi bu konuya özel Flutter’da yeni bir proje başlatın ve aşağıdaki gibi; Sayfa 1, Sayfa 2 ve Sayfa 3 şeklinde üç sınıf oluşturun. Bu üç sayfayı sadece geçişler için kullanacağımızdan herhangi bir içerik girmemize şimdilik gerek yok.

Kodu çalıştırdığımızda Sayfa 1 sınıfı inşa edilecektir ve ekranda aşağıdaki sayfa gözükecektir.

Ekranda bulunan Sayfa 2'ye Git düğmesine basıldığında Navigator.push(…) constructor’ı (yapıcı metodu) tetiklenmiş olacaktır.

Navigator.push iki parametre almaktadır. Biri context, diğeri de yeni sayfayı inşa etmeye yarayan MaterialPageRoute sınıfıdır.

MaterialPageRoute ile anlık olarak bir sayfa tasarımı sunulup, önceki sayfadan gelen kullanıcı, yeni oluşturulan sayfaya yönlendirilmiş olur. Yeni sayfanın özellikleri, MaterialPageRoute içerisindeki builder: parametresi ile verilir.

Sayfa2 sınıfı daha önceden hazır olduğu için builder parametresindeki fonksiyon, direkt olarak Sayfa2'ye döndürülür.

MaterialPageRoute(builder: (context) => Sayfa2())

Böylece birinci sayfadan, ikinci sayfaya geçiş yapmış olduk.

İkinci sayfada iki buton bulunmaktadır. Bunlardan biri Geri dön! diğeri de, Sayfa 3'e Git! butonudur. Üçüncü sayfaya geçiş yapmamızı sağlayan butonda, bir önceki sınıfta olduğu gibi, Navigator.push komutu bulunmaktadır. Birinci sayfadan, ikinci sayfaya nasıl geçtiysek, ikinci sayfadan üçüncü sayfaya da aynı mantıkla geçebiliriz.

Fakat yeniden birinci sayfaya geri dönmek istersek, Navigator.pop(…) komutunu kullanmamız gerekir.

Geri dön! butonuna basıldığında, onPressed parametresinde görebileceğiniz gibi,

onPressed: () => Navigator.pop(context)

ifadesi yer alır. (Sayfa2 sınıfı, 37. satır) Bu sayede istersek ilk sayfaya geri dönebiliriz. Geri dönme işlemini bu butonla yapabildiğimiz gibi, cihazımızda bulunan Geri düğmesi ile de aynı işlemi yapabiliriz. Ayrıca tasarımımızda bir AppBar kullandığımız için, otomatik olarak AppBar üzerinde de bir geri dönme butonu aktif olacaktır. Üstteki resimde geri dönme işlemini yapabileceğimiz üç bölge kırmızı yuvarlakla gösterilmiştir.

Navigator.push, MaterialPageRoute ve Navigator.pop ile sayfa geçişleri

Böylece üçüncü sayfaya gelmiş olduk. Sayfa 3 sınıfında da görebileceğiniz gibi, üçüncü sayfada sadece bir Geri dön! butonu bulunur ve bizi ikinci sayfaya taşır.

Bu şekilde hazırladığımız bu üç sayfa arasında kolaylıkla geçiş yapabildik. Şimdi biraz daha ayrıntıya girelim.

2) Navigator.pushReplacement

Bazen sayfalar arasında dolaşırken, kullanıcının önceki sayfaya dönmemesini istediğimiz durumlar olabilir. Örneğin, bir Login sayfasından doğru şifre ve kullanıcı adı ile giriş yapıp, yeni bir sayfaya gelen kullanıcının, (zaten giriş yapmış olduğu için) yeniden Login sayfasına gitmesini engellemek isteyebiliriz.

İşte bu ve buna benzer durumlar için, Navigator.push yerine Navigator.pushReplacement(…) yapıcı metodunu kullanabiliriz. Bu sayede girilen sayfadan bir önceki sayfaya gidiş mümkün olmayacaktır.

Yukarıda verdiğimiz kodda bazı değişiklikler yaparak, bu örneği de önceden hazırladığımız 3 sayfa ile yeniden deneyebiliriz.

Değişen ikinci kodumuzda, Sayfa 1 sınıfını inceleyelim. Önceki kodda, Navigator.push(…) olarak kullanılan bölümün, şimdi Navigator.pushReplacement(…) ile değiştirildiğini görüyoruz. Bu durumda ikinci sayfaya geçtiğimizde, birinci sayfaya Navigator.pop(…) ile geri dönmek mümkün değildir. Sayfa 2 sınıfını incelediğimizde, önceki kodda yer alan Geri dön! butonunun kaldırıldığını görüyoruz. Çünkü ikinci sayfaya Navigator.pushReplacement ile gelindiği için, birinci sayfa artık yok hükmündedir. Aynı şekilde AppBar üzerinde de geri dönme butonu aktif edilmemiştir ve cihazdaki Geri tuşuna basıldığında da uygulamadan çıkıldığını deneyerek görebilirsiniz.

Sayfa 2 sınıfında yorumla kapatılan bölümü aktif edip, denerseniz hatalı bir ekran görüntüsü alacağınızı görebilirsiniz. O yüzden, Navigator.pushReplacement(…) yapıcı metodunu kullanırken, bu durumu mutlaka göz önünde bulundurmanız gerekir.

Eğer kullanıcının bir şekilde mutlaka önceki sayfaya erişmesi gerekiyorsa, bunun Navigator.pop ile değil, yeniden Navigator.push veya Navigator.pushReplacement veya benzeri bir yapıcı metodla gerçekleştirilmesi gerekir.

Navigator.pushReplacement

3) Routes, Navigator.pushNamed

Bu başlıkta kullanacağımız yöntem, aslında ilk olarak verdiğimiz kodla aynı şekilde çalışmaktadır. Tek farkı MaterialPageRoute sınıfının kullanılmaması ve Navigator.push(…) yerine Navigator.pushNamed(…) yapıcı metodunun kullanılmasıdır. Bu yöntemde, MaterialApp sınıfımızın bir parametresi olan routes: ile tüm sayfalarımızı bir araya getireceğiz ve toplu olarak ilgili sayfaya yönlendirmeler yapmış olacağız. Ayrıca uygulama içerisindeki her sayfamız, tıpkı web sitesi sayfaları gibi, isimlendirilmiş (yani Named) olacak, kodumuz daha pratik bir hale gelmiş olacaktır.

Navigator.pushNamed yapıcı metodu, Navigator.push gibi iki parametre alır. Bunlardan ilki context, diğeri de MaterialApp sınıfında routes: olarak sunulan map’teki herhangi bir anahtar değeridir. Aşağıdaki örneğe bakacak olursak, Navigator.pushNamed’in ikinci parametresine / veya /sayfa2 veya /sayfa3 girilebilir.

Kod içerisinde yer alan MaterialApp sınıfının initialRoute: parametresi, başlangıç sayfasının hangisi olacağını belirlememizi sağlar. Eğer koddaki ilgili bölümü /sayfa2 şeklinde ayarlayıp, kodu kaydedip, uygulamayı yeniden başlatırsanız, uygulama 2. sayfa ile başlayacaktır.

4) Navigator.pushReplacementNamed

Yapıcı metodun isminin uzunluğu bizi kesinlikle korkutmasın :) yeni veya diğerlerinden çok farklı bir yöntem de değildir. Navigator.push ile Navigator.pushReplacement arasındaki farkı üstteki anlatımlardan zaten biliyoruz.

İşte bu noktada, Navigator.pushNamed ile Navigator.pushReplacementNamed arasında da aynı fark veya ilişki diyebileceğimiz bir yapı vardır. Navigator.pushNamed ile gidilen bir sayfada, kullanıcının önceki sayfaya geri dönememesini istiyorsak, Navigator.pushReplacementNamed(…) yapıcı metodunu kullanabiliriz.

Üstte Navigator.pushReplacement’i anlattığım bölümde önceki sayfaya geri dönmeyi sağlayan, Navigator.pop yapıcı metodunun kullanılmaması gerektiğini belirtmiştim. Aynı uyarı Navigator.pushReplacementNamed için de geçerlidir.

5) Navigator.pushAndRemoveUntil & Navigator.pushNamedAndRemoveUntil

Uygulamamız içerisindeki sayfalar arasında geçiş yaparken, örneğin dördüncü sayfadan ilk sayfaya veya belirli bir sayfaya (diğer sayfaları silerek) gitmek isteyebiliriz. Böyle bir durumda, Navigator.pushAndRemoveUntil(…) veya Navigator.pushNamedAndRemoveUntil(…) yapıcı metodlarını kullanabiliriz.

Şimdi kodumuza bir sayfa daha ekleyerek 4 sayfalı bir uygulama yazalım.

Kodu çalıştırdığımızda, uygulamada dördüncü sayfaya gelindiğinde, bizi sadece bir adet Geri dön! butonu bekliyor olacak. Bu buton daha önceki örneklerde de var olan Navigator.pop(…) komutu içeren bir butondur. Normalde bu butona basıldığında üçüncü sayfaya gidilmesi beklenir. Fakat Sayfa3 sınıfında Navigator.pushNamedAndRemoveUntil(…) kullanıldığı için durum biraz değişmiştir.

Navigator.pushNamedAndRemoveUntil yapıcı metodu 3 parametre almaktadır. Birinci parametre her zamanki gibi context, ikinci parametre pushNamed olduğu için MaterialApp sınıfında verilen routes’lardan biri olarak yazılır. (Yani, / veya /sayfa1 veya /sayfa2 veya /sayfa3 gibi...)

Bu kısımda Navigator.pushNamedAndRemoveUntil yerine Navigator.pushAndRemoveUntil(…) de kullanılabilirdi. İkinci parametrede ise MaterialPageRoute sınıfını kullanmak gerekecekti. Bunun örneği de son kodumuzda yorumla kapatılmış olarak (58. ve 64. satırlar arası) gösterilmiştir. Dilerseniz, yorum kısmını açıp, Navigator.pushNamedAndRemoveUntil kısmını kapatarak onun da nasıl çalıştığını görebilirsiniz.

İster Navigator.pushNamedAndRemoveUntil kullanalım, isterse Navigator.pushAndRemoveUntil kullanalım. Her iki durumda da, bu yapıcı metodların üçüncü parametresi olarak, belirli bir sayfaya kadar olan geçmiş sayfaların kaldırılması gerektiğini belirtiriz.

Navigator.pushAndRemoveUntil

Son verilen kodda 71. satırda yer alan;

ModalRoute.withName(‘/’),

bölümü, bize / (slaş) sayfasına kadar, gezilmiş bütün sayfaların silinmesi gerektiğini belirtir. Böylece dördüncü sayfaya gidildiğinde, geri dönülecek tek sayfa “/” ile belirtilmiş olan sayfa olur. Yani dördüncü sayfadan geri gidildiğinde (aradaki sayfalar kaldırıldığı için) birinci sayfaya ulaşılmış olur.

6) Yeni sayfaya basit veri geçişi

Uygulamada sayfadan sayfaya geçiş yaparken, bir sayfada kullanıcıdan edinilen veya başka bir yolla edinilen bir bilgiyi, diğer sayfaya basit bir şekilde taşımak isteyebiliriz. Böyle bir durumda önceden oluşturduğumuz sayfa sınıflarına parametre ataması yapmamız gerekir.

Bu örneği gerçekleştirmek için, yeni kodumuzda toplam sayfa sayımızı ikiye düşürüyoruz. Sayfa2 sınıfımızı parametre alabilecek ve bu parametreyi ekrana yansıtabilecek şekilde yeniden düzenliyoruz.

21. satırdaki koda dikkat ederseniz, birinci sayfadaki bilgi, Sayfa2 sınıfında verilen data: parametresi ile basitçe ikinci sayfaya taşınmış oluyor.

Sayfadan sayfaya basit veri taşınması

7) onGenerateRoute ile sayfalar arası veri geçişleri

MaterialApp içerisindeki routes: parametresini kullandığımız örneklerde dikkat edilirse, rota olarak sabit bir Map sunulmaktadır. Peki sayfa geçişlerinde kullanılabilecek verilerde, herhangi bir değişiklik olması durumunda ne yapacağız?

Yukarıdaki kodda, Sayfa2 sınıfında elle girilmiş bir “sabit data” verisi var. Bu veri bir değişkenle de verilse, aynı durum geçerlidir. Bulunduğu yer itibariyle, veri değişse de, bu değişikliği uygulama arayüzüne aktaramazsınız. İşte böyle bir durumda, devreye MaterialApp sınıfının onGenerateRoute: parametresi girmektedir.

onGenerateRoute: parametresi için tanımlayacağımız özel bir sınıf yardımıyla, sayfadan sayfaya taşınan verilerden güncelleme olması durumunda da sistemimizin sağlıklı çalışmasını sağlamış olacağız.

Bunun için Rotalar adında yeni bir sınıf oluşturuyoruz.

Rotalar sınıfımızda iki statik metod bulunmaktadır. Bunlardan ilki olan generateRoute(…) metodunu, MaterialApp içindeki onGenerateRoute: parametresine sunmak üzere, diğerini de olmayan bir sayfaya gidilmesi durumunda hata mesajını ekrana çıkartmak üzere kullanıyoruz.

Rotalar sınıfındaki generateRoute metodunda, dışarıdan tanımlanan verilerin alınabildiğini ve dinamik olarak sayfalara yönlendirme yapılabildiğini görebiliriz. Yani sayfadan sayfaya taşınan verilerde, değişiklik olsa bile bu metod sayesinde güncel veriler farklı sayfalara taşınabilmektedir.

Son örnek için tüm kodumuz şu hale gelmektedir.

Son kodumuzda, 19. satırdaki Navigator.pushNamed(…) yapıcı metodunun üç parametre aldığını görebiliriz. Üçüncü parametre, taşınacak bilgileri içeren arguments: parametresidir.

Sayfadan sayfaya aktarılan bilgiyi biraz değiştirip, kodu kaydedin. Daha sonra yeniden 1. sayfadaki butona basın. Değişimin hemen ekrana yansıdığını görebileceksiniz. Eğer aynı işlem için MaterialApp içinde routes: parametresini kullansaydık, veriyi değiştirdiğimizde bu değişikliği arayüzde göremeyecektik.

Temel hatlarıyla, Flutter üzerinde sayfa geçişlerini görmüş olduk. Takıldığınız yerleri bu konu altından veya Twitter hesabımdan bana iletebilirsiniz.

  • Muhammed Salih Güler’e sabrı, ilgisi ve emeği için teşekkürü bir borç bilirim. 👍

Zeki ÇIPLAK twitter.com/zekiegitimcom

--

--