Widget — a Flutter keretrendszer központi fogalma, amely a felhasználói felület egy elemének konfigurációját írja le. Minden vizuális komponens, egy gombtól egy összetett animációig, Widget. Más keretrendszerekkel ellentétben, ahol a UI-t külön XML-fájlok írják le vagy imperatív módon rajzolják meg, a Flutter a felületet Widget kompozícióval építi fel — kis oszthatatlan elemek hierarchikus fába történő egyesítésével. A Flutter Documentation (2025) szerint a Flutter SDK könyvtár több mint 260 beépített Widgetet tartalmaz, amelyek lefedik a Material Design, Cupertino és egyedi stílusokat.
Főbb pontok
Widget a Flutterben a felhasználói felület egy részének megváltoztathatatlan (immutable) leírása. Minden Widget konfigurációs tulajdonságokat tartalmaz: méret, szín, pozíció, szöveg, eseménykezelők és gyermek Widgetek. Maguk a Widgetek nem közvetlenül renderelődnek — receptek (blueprints), amelyek alapján a Flutter Engine létrehozza a RenderObject-ot — egy valódi grafikus objektumot a képernyőn.
A Flutter filozófiája azt mondja: „Everything is a Widget”. Ez azt jelenti, hogy nem csak a látható elemek (Text, Image, Button) Widgetek, hanem a strukturális blokkok (Padding, Center, Column, Stack), viselkedési blokkok (GestureDetector, AnimatedBuilder), sőt maga az alkalmazás is (MaterialApp, CupertinoApp). Ez a megközelítés egységességet biztosít: a képernyő bármely eleme kombinálható bármely másikkal egyszerű beágyazással.
A Google I/O 2024 — Flutter Widgets Deep Dive adatai szerint egy átlagos Flutter-alkalmazás egy adott pillanatban 200 és 1500 között tartalmaz Widgetet. Ennyi Widget ellenére a Flutter 60 FPS-t tart fenn még belépő szintű eszközökön is a C++ Skia/Impeller motor szintű optimalizálásoknak köszönhetően. A Widgetek könnyű objektumok (egyenként 40–80 bájt), így létrehozásuk nem teljesítménybeli szűk keresztmetszet.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Center(
child: Text('Helló, Flutter!'),
),
),
);
}
}
Ahhoz, hogy megértsük, hogyan működik a Widget, ismernünk kell a Flutter architektúráját, amely három összekapcsolt fából áll. Az első — Widget tree — a UI konfigurációját írja le. Ez egy könnyű fa, amely minden képkockánál teljesen újjáépíthető (a garbage collector eltávolítja a régi Widgeteket és újakat hoz létre). A Widgetek megváltoztathatatlanok (immutable): ha megváltozott a szöveg színe — létrejön egy új Text Widget az új színnel, a régi eldobásra kerül.
A második fa — Element tree — a kapcsolat a Widget és a RenderObject között. Az Element tartalmaz egy hivatkozást a Widget-re (konfiguráció) és a RenderObject-re (renderelés). Amikor a Widget megváltozik, a Flutter összehasonlítja az új Widgetet a régi Elemmel, és eldönti: frissíti a meglévő RenderObject-ot (ha a Widget azonos típusú) vagy létrehoz egy újat (ha a Widget típusa megváltozott). Ezt a folyamatot Reconciliation-nek hívják, és a React Virtual DOM analógja.
A harmadik fa — RenderObject tree — felelős a tényleges képernyőn történő renderelésért. A RenderObject konkrét méreteket, pozíciókat és paint metódusokat tartalmaz. A Flutter Engine (C++ Skia vagy Impeller) végighalad a RenderObject tree-n, és rendereli az egyes csomópontokat. A RenderObject tree a legnehezebb fa, ezért a Flutter minimalizálja a változtatásait azáltal, hogy újrahasználja a RenderObject-ot azonos típusú Widget cseréjekor.
| Fa | Cél | Immutable? | Életciklus |
|---|---|---|---|
| Widget | UI konfiguráció (recept) | Igen | Minden buildkor újra létrejön |
| Element | Kapcsolat Widget ↔ RenderObject | Nem | Addig létezik, amíg a widget a fában van |
| RenderObject | Renderelés és layout | Nem | Nehéz, újrahasznosítható ha lehetséges |
A Flutter két alapvető típusra osztja a Widgeteket: StatelessWidget és StatefulWidget. A StatelessWidget egy olyan widget, amely nem tartalmaz változó állapotot. A StatelessWidget megjelenését teljes mértékben a konstruktora határozza meg, és a renderelés után nem változhat. Példák: Text, Icon, Divider, Padding. A StatelessWidget összes tulajdonsága final-ként van deklarálva a konstruktorban, és csak olvasható.
StatefulWidget egy változó állapotú widget. Két osztályból áll: magából a Widgetből (változtathatatlan konfiguráció, mint a StatelessWidget) és a State-ből (változó állapot). A Widget és az State szétválasztása kulcsfontosságú architektúrális döntés a Flutterben. A Widget minden buildkor újra létrejön, de az State objektum életben marad a widget teljes életciklusa alatt a fában, megőrizve az állapotát.
Amikor a setState() meghívásra kerül, a Flutter „piszkosnak” jelöli az State-et, és a következő képkockánál meghívja a build() metódust a részfa újjáépítésére. Fontos: a setState() nem hozza létre újra magát a Widgetet — csak kiváltja a build() hívást a meglévő State-ben. Ez azt jelenti, hogy a StatefulWidget frissítheti a UI-t anélkül, hogy elveszítené a gyermek Widgetek állapotát, amíg a gyermek elemek kulcsai (Key) stabilak maradnak.
// StatelessWidget — megjelenés soha nem változik
class GreetingWidget extends StatelessWidget {
const GreetingWidget({super.key, required this.name});
final String name;
@override
Widget build(BuildContext context) {
return Text('Helló, $name');
}
}
// StatefulWidget — számláló változó állapottal
class CounterWidget extends StatefulWidget {
const CounterWidget({super.key});
@override
State<CounterWidget> createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Számláló: $_count'),
ElevatedButton(
onPressed: () => setState(() => _count++),
child: const Text('Növel'),
),
],
);
}
}
A Flutterben lévő összes Widget funkcionális cél szerint három fő kategóriába sorolható. Layout Widget — felelősek a gyermek elemek képernyőn történő elhelyezéséért. A Row és Column sorba rendezi a gyermekeket, a Stack egymásra helyezi őket, az Expanded és Flexible elosztja a rendelkezésre álló helyet. A Layout Widgeteknek nincs saját vizuális megjelenítésük — a gyermek widgetek pozícióját és méretét kezelik.
Painting Widget — felelősek a vizuális megjelenésért. A Container egyesíti a dekorációkat (szín, gradient, árnyék, szegély) a layout tulajdonságokkal. A Padding térközt ad hozzá, a DecoratedBox hátteret rajzol, a Transform transzformációkat alkalmaz (forgatás, méretezés). A Painting Widgetek a vizuális stílus építőkövei, és gyakran használják együtt layout Widgetekkel a kívánt megjelenés eléréséhez.
Interactive Widget — feldolgozzák a felhasználói bemenetet. A GestureDetector gesztusokat érzékel (tap, swipe, pinch), az InkWell Material hullám effektust ad hozzá, a TextField szöveges bemenetet fogad, a Slider és Switch szabványos vezérlőelemeket biztosít. Az Interactive Widgetek eseményeket emelnek callback függvényeken keresztül, amelyek a konstruktorba kerülnek vagy állapotszolgáltatókon keresztül kezelődnek.
| Kategória | Widget példák | Cél |
|---|---|---|
| Layout | Row, Column, Stack, Expanded, Flexible, Align | Gyermek elemek elhelyezése és mérete |
| Painting | Container, Padding, DecoratedBox, RotatedBox | Szín, háttér, szegélyek, árnyékok, transzformációk |
| Interactive | GestureDetector, InkWell, TextField, Slider | Érintés, bevitel, gesztusok feldolgozása |
| Platform | MaterialApp, CupertinoApp, Theme, MediaQuery | Platform integráció, témák, adaptáció |
| Async | FutureBuilder, StreamBuilder, ValueListenableBuilder | Reaktív frissítés aszinkron adatokból |
A Flutter Widget of the Week (Google, 2025) adatai szerint a Flutter közösség aktívan használja a layout + painting + interactive Widget kombinációját szinte bármilyen felület építéséhez. Például egy gomb: InkWell (interactive) + Container (painting) + Text (static) + Padding (layout). Ez a modularitás lehetővé teszi a szabványos blokkok újrafelhasználását különböző kontextusokban kódduplikáció nélkül.
Widget kompozíció a UI építésének folyamata Widgetek egymásba ágyazásával. Ellentétben a klasszikus öröklődéssel (extends), ahol a gyermek osztály örökli a szülő viselkedését, a Flutter aggregációt használ: minden Widget más Widgeteket tartalmaz a child (egyhez) vagy children (többhöz) paraméteren keresztül. Ez a megközelítés nagyobb rugalmasságot és újrafelhasználhatóságot biztosít.
BuildContext a második legfontosabb fogalom a Widget után. A BuildContext a Widget pozíciójának leírója az elemek fájában. A BuildContext-en keresztül a Widget hozzáférhet az őse Widgetekhez (Theme.of(context), MediaQuery.of(context), Navigator.of(context)). A BuildContext a build() metódusba kerül, és a szülő és gyermek elemekkel való interakcióra használják. Minden Widgetnek pontosan egy BuildContext-je van, amely egyedileg azonosítja a pozícióját a fában.
A Flutter Architectural Overview (Google, 2025) szerint a BuildContext az InheritedWidget alapja — egy olyan mechanizmus, amely lehetővé teszi adatok lefelé történő továbbítását a fában anélkül, hogy explicit módon átadnánk azokat konstruktorokon keresztül. A Theme, MediaQuery, Navigator és Provider az InheritedWidget-et használja a motorháztető alatt. Bármely mélyen beágyazott Widget hozzáférhet az ős adataihoz a BuildContext.dependOnInheritedWidgetOfExactType segítségével, ami a BuildContext-et a Flutter reaktív architektúrájának kulcsává teszi.
// Widget kompozíció beágyazással
Scaffold(
appBar: AppBar(title: const Text('Saját App')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Üdvözöl a Flutter',
style: TextStyle(fontSize: 24)),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () { /* nav */ },
child: const Text('Kezdés'),
),
],
),
),
)
// Témák elérése BuildContext-en keresztül
Text(
'Stílusos Szöveg',
style: Theme.of(context).textTheme.headlineMedium,
)
Az első és leggyakoribb hiba — StatefulWidget használata ott, ahol a StatelessWidget is elég. Sok kezdő Flutter-fejlesztő minden widgethez StatefulWidget-et hoz létre, még akkor is, ha az állapot egy külső szolgáltatóban (Provider, Riverpod, BLoC) van tárolva. Ez felesleges és rontja a teljesítményt. Szabály: használj StatelessWidget-et, ha az állapotot kívülről kezelik, vagy ha a widgetnek nincs saját változó állapota.
A második hiba — Widget létrehozása a build metóduson belül const konstruktor nélkül. Minden const nélkül létrehozott Widget minden buildkor újra allokálódik. Ha a build()-ben const konstruktorral hozzuk létre a Widgeteket, a Flutter ugyanazt a példányt használhatja újra, csökkentve a garbage collector terhelését. Adj hozzá const-ot mindenhol, ahol lehetséges — különösen a Text, Icon, SizedBox, Padding és más StatelessWidget esetében.
A harmadik hiba — helytelen munka a kulcsokkal (Key). A Flutter a Key-t használja a Widgetek azonosítására a fa újjáépítésekor. Ha egy Widget lista Key nélkül épül újjá, a Flutter összekeverheti az elemek sorrendjét, ami helytelen animációhoz vagy állapotvesztéshez vezet. Mindig adj hozzá Key-t (pl. ValueKey vagy ObjectKey) a listák elemeihez, különösen a ListView.builder használatakor dinamikus adatokkal.
Gyakran Ismételt Kérdések
StatelessWidget — változó állapot nélküli widget, megjelenését teljes mértékben a konstruktor határozza meg. StatefulWidget — változó állapotú widget, amely egy külön State objektumban van tárolva, és setState()-en keresztül frissíthető anélkül, hogy magát a widgetet újra létrehoznánk. Használj StatelessWidget-et ahol lehetséges, StatefulWidget-et — amikor helyi állapot szükséges.
Widget immutable — a Flutter architektúrális döntése a teljesítmény érdekében. Ha a Widgetek mutable-ek lennének, a Flutter nem tudná biztonságosan összehasonlítani a régi és új konfigurációt minden buildkor. A megváltoztathatatlanság lehetővé teszi a Flutter számára, hogy gyorsan meghatározza, változott-e a Widget (a == operátoron keresztül), és újrahasználja a meglévő RenderObject-ot, minimalizálva a költséges renderelési műveleteket.
BuildContext a Widget pozíciójának leírója az elemek fájában. Rajta keresztül a Widget hozzáfér az őse Widgetekhez (Theme, MediaQuery, Navigator) és az InheritedWidget-hez. A BuildContext-ot használják navigációra (Navigator.of(context)), SnackBar megjelenítésére és a Provider-rel való interakcióra is. Minden Widget a build() metóduson keresztül kapja meg a BuildContext-et, és továbbadja az utódainak.
Használj Row-t elemek vízszintes elrendezéséhez, Column-t — függőleges elrendezéshez, Stack-et — elemek egymásra helyezéséhez. A Row és Column a flexbox elv alapján működik: a children a mainAxisSize, mainAxisAlignment és crossAxisAlignment szerint foglalják el a helyet. A Stack positioned-children-t használ a pontos pozícionáláshoz a szélekhez vagy a középponthoz képest.
A Flutter három mechanizmus révén ér el magas teljesítményt: (1) Widget are cheap — könnyű immutable objektumok (40–80 bájt), létrehozásuk nem terheli a GC-t. (2) RenderObject reuse — azonos típusú Widget cseréjekor a RenderObject újrahasznosításra kerül, elkerülve a költséges újrateremtést. (3) Skia/Impeller engine — renderelés C++ szinten a rajzolási hívások minimalizálásával a repaint boundaries segítségével.
Összefoglaló
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is