MDC-104 Flutter: Material Advanced Components

Münevver BAHAR
HardwareAndro
Published in
8 min readAug 6, 2020

Merhaba, bu yazımda Flutter Codelabs MDC serisinin sonuncusu olan MDC-104: Material Advanced Components konusundan bahsedeceğim. İlgili seriye buradan ulaşabilirsiniz. Serinin ilk üç codelab’ini tamamladığınızı varsayıyorum bu nedenle MDC-103'ün sonunda elde ettiğimiz uygulama üzerinden devam ediyoruz, keyifli okumalar :)

Ne yapacağız?

Bu codelab’de, Shrine uygulamasındaki kullanıcı arayüzünü “backdrop” adı verilen iki katmanlı bir ui ile değiştireceğiz. Bu backdrop, ana ekranda asimetrik olarak gösterilen ürünleri filtrelemek için kullanılan, seçilebilir kategorileri listeleyen bir menü içermektedir.

MDC-103'ü tamamladıysanız, kodunuzun bu codelab için hazır olması gerekir. MDC-104'ten başlıyorsanız uygulamayı buradan indirebilir veya direkt Github’dan klonlayabilirsiniz.

git clone https://github.com/material-components/material-components-flutter-codelabs.git
cd malzemesi-bileşenleri-çarpıntı-kod etiketleri / mdc_100_series
git checkout 104-başlangıç_ve_103-tam

Projeyi başarılı bir şekilde yükleyip çalıştırdıysanız emülatörde veya simülatörde bu ekranı görmelisiniz.

Buraya kadar sorunsuz geldiğinizi umuyorum, artık başlayabiliriz 🙏

Backdrop Menu Ekleme

Diğer tüm içerik ve bileşenlerin arkasında bir arka plan görünür. İki katmandan oluşur; bir arka katman (eylemleri ve filtreleri görüntüleyen) ve bir ön katman (içeriği görüntüleyen). Gezinme veya içerik filtreleri gibi etkileşimli bilgileri ve eylemleri görüntülemek için bir arka plan kullanabilirsiniz.

Ana ekrandaki appbar’ı kaldırın

HomePage widget’ı ön katmanımızın içeriği olacaktır. Şu anda HomePage’de bir appbar var. Bu appbar’ı arka katmana taşıyacağız ve HomePage yalnızca AsymmetricView’u içerecek.

home.dart dosyasındaki build() fonksiyonunun içerisini yalnızca bir AsymmetricView döndürecek şekilde değiştirin:

Backdrop widget’ını ekleyin

frontLayerve backLayer içeren backdrop isimli bir widget oluşturacağız.

backLayerlisteye filtre için bir kategori seçmemizi sağlayan bir menü içermektedir ( currentCategory). Menü seçiminin devam etmesini istediğimizden, Backdrop'u bir stateful widget haline getireceğiz.

/libklasörü içerisine backdrop.dartisimli yeni bir dosya oluşturun:

Backdrop sınıfı tanımının altına _BackdropState sınıfı ekleyin:

build() fonksiyonu HomePage’deki kullanımı gibi geriye bir appbar ile Scaffold döndürür. Ama Scaffold’un body kısmı bir stack’tir bu nedenle child’ları çakışabilir. Her child’ın boyutu ve konumu stack’in parent’ına göre belirlenir.

Şimdibackdrop.dartve model/product.dartdosyalarını app.dartiçerisine import ediyoruz:

app.dartiçerisindeki build methodunun home: HomePage() olan kısmını backdrop ile değiştiriyoruz:

Uygulamanızı hot reload ederseniz ana sayfanızı ve appbar’ı bu şekilde görmelisiniz.

Shape Ekleme

Bu adımda, sol üst köşeye bir kesim eklemek için ön katmana stil uygulayacağız.

Material Design, bu tür özelleştirmeleri shape olarak ifade eder. Material yüzeyleri rastgele şekillere sahip olabilir. Şekiller yüzeylere vurgu ve stil katar ve markayı ifade etmek için kullanılabilir. Sıradan dikdörtgen şekiller kavisli veya açılı köşeler ve kenarlar ve herhangi bir sayıda kenar ile özelleştirilebilir. Simetrik veya düzensiz olabilirler.

Ön katmana shape ekleyin

backdrop.dartiçerisinde yeni bir _FrontLayer sınıfı ekleyin:

Daha sonra, _BackdropState class’ındaki_buildStack()methodunda, ön katmanına bir _FrontLayer ögesi ekleyin:

Değişiklikleri kaydedin ve tekrar yükleyin.

Motion ekleme

Motion, uygulamanızı hayata geçirmenin bir yoludur. Büyük ve çarpıcı, ince ve minimal veya aradaki herhangi bir yerde olabilir. Ancak, kullandığınız hareket türünün duruma uygun olması gerektiğini unutmayın.

Menu butonuna açıklama motion’ı ekleme

backdrop.dartdosyasında herhangi bir sınıf veya method kapsamı dışında, animasyonumuzun sahip olmasını istediğimiz hızı temsil etmek için bir sabit tanımlıyoruz:

_BackdropState ögesine bir AnimationController widget’ı ekleyin:

Widget lifecycle

initState(), widget render tree’nin bir parçası olmadan önce yalnızca bir kez çağrılır. dispose() ise widget düzgün bir şekilde ağaçtan kaldırıldığında yalnızca bir kez çağrılır.

AnimationController, animasyonları koordine eder, animasyonu oynatmak, ters çevirmek ve durdurmak için API verir. Şimdi onu hareket ettiren fonksiyonlara ihtiyacımız var.

Ön katmanın görünürlüğünü belirleyen ve değiştiren fonksiyonlar ekleyin:

BackLayer’ı bir ExcludeSemantics widget’ına sarın. Bu widget, arka katman görünür olmadığında backLayer’ın menü öğelerini semantic tree’den ayrı tutar.

Bir BuildContext ve BoxConstraints almak için _buildStack () methodunu değiştirin. Ayrıca, RelativeRectTween animasyonu alan bir PositionedTransition ekleyin:

Son olarak, Scaffold body’de _buildStack fonksiyonunu çağırmak yerine , builder olarak _buildStack kullanan bir LayoutBuilder widget’ı döndürün:

Arka planın gerçek toplam yüksekliğini dahil edebilmemiz için LayoutBuilder kullanarak ön / arka katman yığınının yapısını yerleşim süresine kadar erteledik. LayoutBuilder, builder callback’lerinde boyut kısıtlamaları sağlayan özel bir widgettır.

LayoutBuilder

Widget ağacı, yapraklara doğru hareket ederek düzeni gerçekleştirir. Kısıtlamalar ağaçtan aşağı aktarılır, ancak yaprak kısıtlamalara dayanarak yaprak boyutunu döndürene kadar boyutlar genellikle hesaplanmaz. Bir yaprağın ebeveyinin boyutunu bilmesi gerekiyorsa, henüz hesaplanmadığı için yapamaz.

LayoutBuilder, bir widget’ın kendini düzenlemek için ana widget’ının boyutunu bilmesi gerektiğinde kullanılır (ve ebeveyn boyutu çocuğa bağlı değildir.) LayoutBuilder, Widget döndüren bir işlevi alır.

Daha fazla bilgi için LayoutBuilder sınıfı belgelerine bakın.

build()fonksiyonu içerisinde, appbar’da leading menüsü simgesini açmak ve butona tıklandığında front layer’ın görünürlüğünü değiştirmek için bir IconButton kullanabilirsiniz.

Uygulamayı yeniden yükleyin ve menu butonuna tıklayın, burada bir taşma hatası alacaksanız. Bunun nedeni, AsymmetricView’ün bu animasyon tarafından sıkıştırılması ve daha küçük hale gelmesi ve dolayısıyla column’lara daha az yer açmasıdır. Sonunda, column’lar verilen boşlukla kendilerini düzenleyemezler ve bir hatayla sonuçlanırlar. Column’ları ListViews ile değiştirirsek, column boyutu hareket ettikçe kalmalıdır.

ListView’da ürün column’ları ekleyin

supplemental/product_columns.dart, dosyasındaki OneProductCardColumn’ını bir ListView ile değiştirin:

Column MainAxisAlignment.endiçerir. Düzene alttan başlamak için reverse: trueyapıyoruz. Değişikliği düzeltmek için child’ların sırası tersine çevrildi.

supplemental/product_columns.dartdosyasında TwoProductCardColumn ‘ındaki imageAspectRatiohesaplanma şeklini değiştirin ve Column’ı bir ListView ile değiştirin:

Uygulamayı yeniden yükleyin, artık taşma sorunumuz kalmadı.

Arka katmana menu ekleme

Menü, metin ögelerine dokunulduğunda dinleyicileri bilgilendiren, dokunulabilir metin ögelerinin bir listesidir. Bu adımda, bir kategori filtreleme menüsü ekleyeceğiz.

Menüyü ekleyin

Menüyü ön katmana ve etkileşimli düğmeleri arka katmana ekleyin.

lib/category_menu_page.dartisimli yeni bir dosya oluşturun:

app.dart,içerisindeki ShrineApp widget’ını stateless widget’tan stateful widget’a çevirin:

  1. İmlecinizi StatelessWidget üzerine getirin
  2. Alt + enter tuşlarına basın
  3. Convert to StatefulWidget’a tıklayın

Şimdi _ShrineAppState widget’ına bir category değişkeni tanımlayın ve dokunulduğunda gerçekleşecek bir callback ekleyin:

Daha sonra CategoryMenuPage’i import edin ve build() fonksiyonu içerisindeki back layer’ı bir CategoryMenuPage olarak değiştirin:

Uygulamayı yeniden yükleyin ve menu butonuna tıklayın.

Menü seçeneklerimiz geldi ancak şu an tıkladığınızda hiçbir şey olmaz. Bunu düzeltmek için home.dartdosyasına kategori için bir değişken ekleyin ve bunu AsymmetricView öğesine iletin:

app.dartiçerisindeki frontLayer kısmına da _currentCategory'iatın:

Değişiklikleri kaydedip tekrar yükleyin. Menü butonuna tıklayıp herhangi bir kategoriyi seçin tekrar menü butonuna tıkladığınızda filtreleme işleminin gerçekleştiğini göreceksiniz.

Menüden bir seçimin yapıldıktan sonra front layer’ı kapatın

backdrop.dartdosyasında _BackdropState içindeki fonksiyon için bir override ekleyin didUpdateWidget():

Yeniden yükleme sonrasında menü simgesine dokunun ve bir kategori seçin. Menü otomatik olarak kapanmalı ve seçilen ögelerin kategorisini görmelisiniz. Şimdi bu methodu ön katmana da ekleyeceğiz.

Ön katmanı aç / kapat

backdrop.dartdosyasında arka plan katmanına hafifçe dokunarak gerçekleşen bir callback ekleyin:

Daha sonra _FrontLayer’ın child’ına bir GestureDetector ekleyin:

Ardından _BackdropState içerisindeki _buildStack() methoduna onTap özelliğini ekleyin:

Yeniden yükleyin ve ardından Front Layer’ın üstüne dokunun. Front Layer’ın üstüne her dokunduğunuzda katman açılıp kapanmalıdır.

Branded icon ekleme

backdrop.dartdosyasında _BackdropTitle isimli yeni bir sınıf oluşturun:

_BackdropTitleAppBar widget’ının title parametresi için text widget’ının yerini alacak özel bir widget’tır. Animasyonlu bir menü iconuna ve ön başlık ile arka başlık arasında animasyonlu geçişlere sahiptir. Animasyonlu menü iconu yeni bir asset kullanacak. Bu nedenle pubspec.yamldosyasına slanted_menu.pngisimli yeni bir reference eklemelisiniz:

backdrop.dart dosyasında AppBarbuilder’daki leadingözelliğini kaldırın. Branded iconun orijinal leadingwidget'ın yerinde görüntülenmesi için kaldırılması gerekir. AppBariçerisinde titleparametresi oluşturun:

Flutter’ın “her şey bir widgettır” mimarisi, yeni özel bir AppBarwidget oluşturmak zorunda kalmadan AppBar’ın varsayılan layout’ının değiştirilmesini sağlar. titleparametresinin orjinal widget’ı Textolmasına rağmen, daha komplex bir yapı olan _BackdropTitleile değiştirebildik.

Giriş ekranına bir kısayol ekleyin

backdrop.dartdosyasına appbar’da yer alan sondaki iki icon’dan login ekranına geri dönülmesini sağlayan bir kısayol ekleyin:

Bu codelab’de yer alan tüm adımları tamamladık uygulamamızın son hali aşağıdaki gibidir. Projenin kaynak kodlarına buradan ulaşabilirsiniz.

Biraz uzun bir yazı oldu ama yeni başlayanlar için açıklayıcı olmasını istedim, umarım yardımcı olur.

Bir sonraki yazıda görüşmek üzere, hoşçakalıın😊

--

--