Flutter SK/CZ – #1.10 – Image Carousel & Carousel Slider [Detail Galérie]

Úvod

Vitajte v Himdeve development, kde pre Vás pripravujeme tie najlepšie tutoriály, ktoré Vám uľahčia a zefektívnia vývoj mobilných aplikácií.

Cieľ

  1. Vytvoríme detail stránku pre galériu obrázkov
  2. Naučíme sa pracovať s komponentami PhotoView a PhotoViewGallery
  3. Naučíme sa vytvoriť si vlastný Image Carousel a takisto aj využiť komponent Carousel Slider
  4. Ukážeme si ako vytvoriť ripple efekt animáciu na kliknutie na obrázok
  5. Naučíme sa ako zväčšovať, zmenšovať a rotovať obrázok
  6. A taktiež si ukážeme ako pracovať s Flutter widgetmi ako je Stack, Positioned a InkWell

Postup

Najskôr otvoríme našu existujúcu aplikáciu z predchádzajúceho tutoriálu a otvoríme portfolio_gallery_sub_page.dart súbor. Toto bude náš vstupný súbor pre tento tutoriál.

V _buildContent metóde pre SliverGrid delegát vraciame metódu _buildImageWidget. Vytiahneme túto metódu do nového súboru portfolio_gallery_image_widget.dart v priečinku components. Bude to Stateless Widget s dvomi povinnými parametrami – imagePath a onImageTap. ImagePath reprezentuje cestu k danému obrázku a onImageTap je void callback funkcia, ktorá bude reagovať na kliknutie na obrázok.

Ripple Efekt

Ripple efekt alebo teda Zvlnenie je malý vzor podobný vlne, ktorý sa zvyčajne vytvára na povrchu nejakej tekutiny, keď na ňu niečo dopadne.

Vo Flutteri ripple efekt predstavuje vizuálnu spätnú väzbu dotyku na interakciu používateľa s komponentami na obrazovke.

Flutter poskytuje widget InkWell na vykonanie daného efektu.

InkWell môže zabalovať jednotlivé widgety a poskytnúť tak vrstvu pre ripple efekt.

InkWell má atribút onTap, do ktorého vložíme našu onImageTap callback metódu.

Ako spojiť InkWell a náš obrázok dokopy?

Vo Flutteri je na to ideálny komponent Ink, kde využijeme jeho konštruktor Ink.image.

Ink.image konštruktor má atribúty:

  • image: do ktorého pomocou AssetImage providera vložíme cestu k danému obrázku v našom assets priečinku.
  • fit: do ktorého vložíme BoxFit.cover.
  • child: do ktorého vložíme InkWell widget.

Aby mal ripple efekt miesto, kde sa môže prejaviť, tak zaobalíme Ink.image konštruktor do Material widgetu.

Copy to Clipboard

Následne celá táto trieda vyzerá nasledovne.

Copy to Clipboard

Vrátime sa do portfolio_gallery_sub_page.dart súboru a namiesto metódy _buildImageWidget vrátime widget PorfolioGalleryImageWidget. ImagePath atribút nastavíme na konkrétnu cestu k obrázku a do atribútu onImageTap vložíme Navigator.push metódu na zmenu stránky. Prepneme sa na stránku PortfolioGalleryDetailPage. Využijeme na to MaterialPageRoute, ktorý vytvoríme v metóde _createGalleryDetailRoute. PortfolioGalleryDetailPage bude mať atribúty imagePaths, ktorý reprezentuje list ciest k obrázkom a currentIndex, ktorý reprezentuje aktuálne zvolený index obrázku.

Copy to Clipboard
Copy to Clipboard

PortfolioGalleryDetailPage

PortfolioGalleryDetailPage triedu je nutné najskôr vytvoriť. Preto vytvoríme súbor portfolio_gallery_detail_page.dart v priečinku pages/portfolio.

Bude to Stateful Widget. Zadefinujeme mu povinné parametre imagePaths a currentIndex.

Pre jeho stav – _PortfolioGalleryDetailPageState triedu, zadefinujeme dve premenné – _currentIndex a _pageController.

A v initState metóde ich inicializujeme.

Copy to Clipboard

Aby sme získal currentIndex zo Stateful Widgetu do State triedy, tak použijeme getter widgetwidget.currentIndex.

PageController bude slúžiť na manipuláciu medzi stránkami našich obrázkov aby sme dosiahli efekt Image Carouselu. Zadefinujeme mu argument initialPage, vďaka ktorému zobrazíme aktuálne zvolený obrázok.

V build metóde vrátime Scaffold widget, ktorému nastavíme čiernu farbu pozadia a pridáme AppBar widget aby sme mali tlačítko späť na vrátenie sa na predchádzajúcu stránku. Takisto zadefinujeme jeho farbu pozadia na čiernu. Do atribútu body, vložíme metódu _buildContent().

Copy to Clipboard

Stack

Zadefinujeme _buildContent() metódu. Vrátime v nej Stack widget.

Stack widget umožňuje vzájomné prekrývanie viacerých widgetov. V našom prípade to využijeme spôsobom, že najskôr vložíme widget, ktorý zobrazí daný obrázok v galérií obrázkov a cez neho na spodku zobrazíme indikátor pás našich obrázkov v liste.

Copy to Clipboard

PhotoViewGallery – Image Carousel

V _buildPhotoViewGallery metóde vrátime PhotoViewGallery pomocou konštruktora PhotoViewGallery.builder. Keby sme chceli explicitne definovať obrázky v galérii, tak použijeme konštruktor PhotoViewGallery(). PhotoViewGallery.builder konštruktor vytvára obrázky v galérii dynamicky.

Aby sme mohli vôbec použiť PhotoViewGallery, potrebujeme zadefinovať photo_view dependency do pubspec.yaml súboru.

Copy to Clipboard

PhotoViewGallery má v sebe zakomponovaný PageView so všetkými efektami, čím máme zabezpečené stránkovanie medzi obrázkami. A tým vyriešenú základnú funkcionalitu Image Carouselu.

PhotoViewGallery.builder konštruktor má niekoľko atribútov. Momentálne zadefinujeme niekoľko z nich.

itemCount

– predstavuje počet položiek a vložíme sem widget.imagePaths.length. Znovu si môžeme všimnúť, že imagePaths parameter, definovaný v Stateful Widgete dostaneme pomocou get metódy – widget.

builder

– slúži na vytvorenie položiek v galérii. Vrátime tu objekt PhotoViewGalleryPageOptions, čo je wrapper, ktorý zabaluje daný obrázok a k nemu prislúchajúce možnosti.

PhotoViewGalleryPageOptions

Zadefinujeme tu takisto niekoľko atribútov.

imageProvider

– do ktorého vložíme AssetImage provider s aktuálnym obrázkom.

minScale

– definuje minimálnu veľkosť, do ktorej bude mať obrázok povolené sa zmenšiť. 

maxScale

– definuje maximálnu veľkosť, do ktorej bude mať obrázok povolené sa zväčšiť.

Ďalšie atribúty PhotoViewGallery.builder.

enableRotation

– povoluje používateľovi rotovať obrázok na obrazovke.

scrollPhysics

– umožňuje meniť efekt stránkovanie jednotlivých obrázkov.

pageController

– sem zadefinujeme náš _pageController.

loadingBuilder

– tento atribút má väčší zmysel, keď načítavame obrázok z internetu, kedy načítavanie môže trvať dlhšiu dobu v závislosti na rýchlosti internetu. Vložíme sem CircularProgressIndicator a zacentrujeme ho na stred.

onPageChanged

– je to callback metóda, ktorá sa zavolá na zmenu zobrazeného obrázku v galérii pri stránkovaní. Má parameter index, ktorý nastavíme našej premennej _currentIndex.

backgroundDecoration

– definuje pozadie za obrázkom, napríklad farbu.

scrollDirection

– definuje smer skrolovania. Môžeme skrolovať horizontálne aj vertikálne.

Copy to Clipboard

PhotoView

V prípade, že by sme nechceli vytvárať galériu, ale chceli by sme zobraziť len jeden obrázok, môžeme využiť triedu PhotoView namiesto PhotoViewGallery, v ktorej vieme takisto zadefinovať predošlé parametre.

Copy to Clipboard

Positioned

Vytvoríme teraz druhú metódu definovanú v Stack widgete_buildIndicator().

V tejto metóde vrátime widget Positioned, ktorý určuje, kde je umiestnený potomok widgetu Stack

Má niekoľko atribútov. Nastavíme mu atribút bottom na 0, čím zabezpečíme, že spodok daného child-widgetu bude umiestenený na spodku Stack widgetu.

Atribút left aj atribút right nastavíme na 0. Kedže obidva atribúty sú nastavené na 0, tak sa child-widget hranami dotýka okrajov Stack widgetu. Čiže je roztiahnutý na šírku Stack widgetu

Dotted Indicator

Následne do atribútu child vložíme Row widget, ktorý zacentrujeme na stred pomocou atribútu mainAxisAlignment. A pre Row atribútu children využijeme map funkciu, ktorá pre každý obrázok v liste vytvorí určitý widget. V našom prípade to bude malá bodka reprezentujúca obrázok v galérii. 

Túto bodku vytvoríme v metóde _buildDot, ktorá bude mať parameter cestu k danému obrázku.

Copy to Clipboard

V _buildDot metóde vykreslíme Container widget, ktorému do decoration atribútu vložíme BoxDecoration v tvare krúžku pomocou atribútu shape. A farbu nastavíme na šedú všetkým bodkám reprezentujúcim obrázky v galérii okrem bodky, ktorá reprezentuje aktuálne zobrazený obrázok. Tejto bodke nastavíme farbu na bielu. Či sa jedná o aktuálne zobrazený obrázok zistíme porovnaním aktuálneho indexu _currentIndex s indexom získaným pomocou list funkcie indexOf.

Copy to Clipboard

Image Carousel Slider

Keby sme chceli namiesto bodiek zobraziť zmenšený image carousel slider na spodku obrazovky, tak môžeme použiť carousel_slider knižnicu. Do pubspec.yaml súboru zadefinujeme carousel_slider knižnicu s aktuálnou verziou ^1.4.1.

Copy to Clipboard

A v portfolio_gallery_detail_page.dart súbore do child atribútu, widgetu Positioned, v metóde _buildIndicator, vložíme metódu _buildImageCarousel().

Copy to Clipboard

Metóda _buildImageCarousel vráti CarouselSlider widget. Máme znovu možnosť použiť explicitný konštruktor CarouselSlider(), alebo dynamický konštruktor CarouselSlider.builder()

Použijeme dynamický konštruktor CarouselSlider.builder().

Tento konštruktor má nasledovné atribúty.

itemCount

– kde nastavíme počet položiek nášho listu obrázkov

itemBuilder

– slúži na vytvorenie položiek. V našom prípade mini obrázkov, na čo znovu môžeme využiť náš PortfolioGalleryImageWidget, ktorý má už v sebe zadefinovaný ripple efekt. Do povinného parametru imagePath vložíme cestu k obrázku. A v atribúte onImageTap zavoláme funkciu PageControllera jumpToPage s indexom zvolenej položky.

height

– nastavuje výšku CarouselSlideru.

enlargeCenterPage

– určuje, či má byť prostredná položka vačšia ako ostatné položky na okrajoch. Dodáva CarouselSlideru dojem zobrazenia do hĺbky.

viewportFraction

– nastavuje šírku stránky v rámci viewportu CarouselSlidera. Nastavíme tento atribút na hodnotu 0.21. Čo znamená, že každá stránka, čiže v našom prípade obrázok, bude zapĺňať 21% veľkosti CarouselSlideru.

initialPage

– definuje aktuálnu stranu CarouselSlideru.

Copy to Clipboard

Záver

A tým je naša desiata časť tejto prvej série Flutter SK/CZ Tutoriálov ukončená a kompletný zdrojový kód môžete samozrejme nájsť na githube.