Flutter widgetek működése és egyedi komponensek létrehozása
A Flutter fejlesztés legnagyobb előnye, hogy a létrehozott alkalmazás teljes szerkezete widgetekből épül fel. Ezek alkotják a Flutter alkalmazások minden vizuális és funkcionális elemét – a legegyszerűbb gomboktól a komplex dizájnig. Cikkünkben bemutatunk néhány alapvető Flutter widgetet és azok használatát, valamint példákon keresztül szemléltetjük az egyedi widgetek létrehozásának lehetőségét.
A Flutter Widget jelentése
A widget a Flutter alkalmazások alapvető építőeleme. Minden vizuális komponens – legyen az gomb, szövegdoboz, kép vagy lista – widget. A Flutter két fő widget típust különböztet meg:
- StatelessWidget: olyan widget, amelynek állapota nem változik futás közben. Ezek statikus elemek, például szövegek vagy ikonok.
- StatefulWidget: olyan widget, amely dinamikus állapotot kezel, azaz az alkalmazás futása közben változhatnak a megjelenített adatok, például egy űrlap bemeneti mezője, vagy egy gomb állapota.
Alapvető Flutter Widgetek
Következzen néhány alapvető widget, amelyekkel találkozhatsz a Flutterben:
1. Text
A Text widget az egyik legegyszerűbb, mégis alapvető elem a Flutter alkalmazásokban. Szövegek megjelenítésére szolgál, és könnyen testreszabható különböző stílusokkal, színekkel és formázásokkal.
Használata:
Text( 'Hello, Flutter!', style: TextStyle( fontSize: 20, color: Colors.blue, ), );
Eredménye:
2. Container
A Container az egyik legfontosabb layout widget a Flutterben, amely szinte minden UI elemhez használható. Rugalmasan állítható be a mérete, színe, margói, alakja, árnyéka és egyéb vizuális paraméterei.
Használata:
Container( width: 150, height: 150, padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 6, ), decoration: BoxDecoration( color: Colors.red, borderRadius: BorderRadius.circular(10), ), child: const Text('Hello, Flutter!'), );
Eredménye:
3. Row és Column
A Row és Column layout widgetek sorba, illetve oszlopba rendezik a gyermek widgeteket, így rugalmasan helyezhetünk el különböző elemeket a képernyőn. A mainAxisAlignment és crossAxisAlignment paramétereik változatos igazítási lehetőségeket kínálnak.
Használata:
Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text('First item'), FlutterLogo(size: 50), Text('Third item'), ], );
Eredménye:
Használata:
Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text('First item'), FlutterLogo(size: 50), Text('Third item'), ], );
4. ListView
A ListView egy görgethető listát biztosít, amely különösen hasznos hosszú tartalmak megjelenítésére, mint például hírek, bevásárlólisták vagy üzenetek.
Használata:
ListView( children: [ Container( height: 50, alignment: Alignment.center, color: Colors.blue[300], child: Text('First item'), ), Container( height: 50, alignment: Alignment.center, color: Colors.blue[200], child: Text('Second item'), ), Container( height: 50, alignment: Alignment.center, color: Colors.blue[100], child: Text('Third item'), ), ], );
Eredménye:
Az alapértelmezett ListView konstruktor kis méretű listákhoz ideális. Ha azonban sok elemmel dolgozol, érdemes a ListView.builder konstruktor használata mellett dönteni. Ez ugyanis - az alapértelmezettel ellentétben -, nem hozza létre egyszerre az összes elemet, hanem csak akkor generálja őket, amikor a görgetés során a képernyőn megjelennek.
final items = ['First item', 'Second item', 'Third item']; final colorCodes = [300, 200, 100]; Widget build(BuildContext context) { return ListView.builder( itemCount: items.length, itemBuilder: (context, index) { return Container( height: 50, alignment: Alignment.center, color: Colors.blue[colorCodes[index]], child: Text(items[index]), ); }, ); }
5. Scaffold
A Scaffold egy alapvető struktúra widget, amely egy tipikus képernyő vázát biztosítja, és olyan elemeket tartalmaz, mint például az appbar (fejléc), floating action button, drawer (oldalsó menü), body.
Használata:
Scaffold( appBar: AppBar( title: Text('Flutter App'), leading: BackButton(), ), body: Center( child: Text('Hello, Flutter!'), ), floatingActionButton: FloatingActionButton( onPressed: () {}, child: Icon(Icons.add), ), );
Eredménye:
6. Stack
A Stack widget segítségével egymásra helyezhetünk több elemet, hasonlóan a rétegezéshez. Ez lehetővé teszi az elemek szabadabb elrendezését, például átfedések vagy widgetek áthelyezését a képernyő különböző pontjaira. A pontos pozicionálás a Positioned widget használatával érhető el.
Használata:
Stack( children: [ Container( color: Colors.blue, width: 100, height: 100, ), Positioned( top: 10, left: 10, child: Container( color: Colors.red, width: 50, height: 50, ), ), ], );
Eredménye:
Egyedi Widgetek létrehozása
A Flutter fejlesztés egyik fő előnye, hogy egyszerűen hozhatsz létre egyedi widgeteket, ha a meglévők nem felelnek meg az igényeidnek. Emellett a kódszervezés és a következetes megjelenés érdekében is kulcsfontosságú elkülöníteni azokat a UI elemeket, amelyek gyakran megjelennek több képernyőn is. Ilyenkor eldöntheted, hogy statikus vagy dinamikus elemeket hozol létre – előbbihez a StatelessWidget, utóbbihoz a StatefulWidget osztályt használhatod.
Stateless Widget példa
Kezdjünk egy egyszerű, statikus egyedi widgettel, amely egy testreszabott gombot hoz létre:
class CustomButton extends StatelessWidget { final String text; final Color color; final VoidCallback onPressed; const CustomButton({ super.key, required this.text, required this.color, required this.onPressed, }); @override Widget build(BuildContext context) { return ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: color, ), onPressed: onPressed, child: Text( text, style: TextStyle(color: Colors.white), ), ); } }
Ez a CustomButton widget egy gombot reprezentál, aminek beállítható a szövege, a színe és a gomb megnyomásakor végrehajtandó művelete a text, color és onPressed paraméterek segítségével. Egy egyszerű felhasználása így néz ki:
CustomButton( text: 'Custom Button', color: Colors.blue, onPressed: () { print('Button pressed'); }, );
Eredménye:
Stateful Widget példa
Most nézzünk meg egy olyan widgetet, amely kívülről kap olyan paramétert, amivel testreszabható, valamint belső állapottal rendelkezik és ennek megfelelően változik.
class PasswordFieldWidget extends StatefulWidget { final String label; const PasswordFieldWidget({ super.key, required this.label, }); @override State<StatefulWidget> createState() => PasswordFieldState(); } class PasswordFieldState extends State<PasswordFieldWidget> { bool hiddenPassword = true; @override Widget build(BuildContext context) { return TextFormField( obscureText: hiddenPassword, decoration: InputDecoration( label: Text(widget.label), suffixIcon: IconButton( icon: Icon(hiddenPassword ? Icons.visibility : Icons.visibility_off), onPressed: () { setState(() => hiddenPassword = !hiddenPassword); }, ), ), ); } }
A példában lévő PasswordFieldWidget egy jelszó beviteli mező, ami label paraméterként kapja a mező nevét, illetve hiddenPassword változó vezérli a mező tartalmának láthatóságát. Egy valós használati eset, amikor jelszóváltoztatás funkciót szeretnénk implementálni az applikációnkba. Ilyenkor két ilyen beviteli mezőt kell használnunk különböző paraméterekkel.
Column( children: [ PasswordFieldWidget(label: 'Current password'), PasswordFieldWidget(label: 'New password'), ], );
Eredménye:
További gyakori példák
- CustomItemCard: Egy testreszabott kártya widget, amely általában képeket, szövegeket és gombokat tartalmaz meghatározott stílusban. Ezeket a widgeteket gyakran használjuk listaelemek megjelenítésére.
- CustomInputField: Egy egyedi beviteli mező, amely túlmutat az alapértelmezett TextField funkcióin. Jellemzői a speciális validáció, egyedi ikonok, testreszabott háttér és sajátos megjelenés.
- CustomAppBar: Egy app dizájn implementációja során gyakran hozunk létre egy specifikus appbar widgetet, amely egységes megjelenést biztosít minden képernyőn. Az ilyen widget gyakori paraméterei közé tartozik a képernyő neve, vagy a vissza gomb megnyomásakor végrehajtandó művelet.
Hasznos tippek
- Kisebb komponensek: Ne félj a kisebb elemeket külön widgetekbe kiemelni. Az egyedi widgetek így könnyen újrafelhasználhatók és karbantarthatók lesznek.
- Belső állapot kezelése: Amikor állapotot kezelő widgetet hozol létre, gondolj a teljesítményre is. Csak akkor frissítsd a widgetet, ha valóban szükséges.
- Kompozíció: A Flutter fejlesztés során ajánlott a kompozíciót használni az öröklés helyett, ezért inkább több kis widgetet komponálj egymásba.
A beépített Flutter widgetekre építve gyorsan hozhatsz létre UI elemeket, míg az egyedi widgetek lehetővé teszik, hogy testreszabott és konzisztens felhasználói élményt nyújts.