Widget — mi ez, típusok és kompozíció Flutterben

Szerző: IT Sectr Megjelenés: 2026-06-30 Olvasási idő: 10 perc

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 UI alapvető építőeleme Flutterben, amely egy elem konfigurációját írja le.
  • Kompozíció — a UI Widgetek egymásba ágyazásával épül, nem öröklődéssel.
  • StatelessWidget — widget, amely a renderelés után nem változik (szöveg, ikon, térköz).
  • StatefulWidget — widget változó állapottal (űrlapok, animációk, adatlisták).
  • Element tree — a Flutter három fát tart fenn: Widget, Element és RenderObject.

Mi az a Widget Flutterben

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.

dart
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!'),
        ),
      ),
    );
  }
}

A Flutter három fája: Widget, Element és RenderObject

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.

FaCélImmutable?Életciklus
WidgetUI konfiguráció (recept)IgenMinden buildkor újra létrejön
ElementKapcsolat Widget ↔ RenderObjectNemAddig létezik, amíg a widget a fában van
RenderObjectRenderelés és layoutNemNehéz, újrahasznosítható ha lehetséges

StatelessWidget vs StatefulWidget

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.

dart
// 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'),
        ),
      ],
    );
  }
}

Widget típusok: layout, painting, interactive

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óriaWidget példákCél
LayoutRow, Column, Stack, Expanded, Flexible, AlignGyermek elemek elhelyezése és mérete
PaintingContainer, Padding, DecoratedBox, RotatedBoxSzín, háttér, szegélyek, árnyékok, transzformációk
InteractiveGestureDetector, InkWell, TextField, SliderÉrintés, bevitel, gesztusok feldolgozása
PlatformMaterialApp, CupertinoApp, Theme, MediaQueryPlatform integráció, témák, adaptáció
AsyncFutureBuilder, StreamBuilder, ValueListenableBuilderReaktí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ó és BuildContext

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.

dart
// 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,
)

Gyakori hibák Widgetekkel

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

Mi a különbség a StatelessWidget és a StatefulWidget között?

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.

Miért nevezik a Widgeteket immutable-nek?

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.

Mi az a BuildContext és mire való?

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.

Hogyan válasszak a Row, Column és Stack között layout-hoz?

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.

Hogyan tart fenn a Flutter 60 FPS-t több ezer Widgettel?

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ó

  • Widget — a UI egy részének immutable konfigurációja Flutterben, alapvető építőelem, amely leírja a megjelenést és viselkedést.
  • Három fa — a Flutter a Widget tree (konfiguráció), Element tree (kapcsolat), RenderObject tree (renderelés) használja optimális megjelenítéshez.
  • Stateless vs Stateful — StatelessWidget állapot nélkül, StatefulWidget változó State-tel és setState() metódussal a UI frissítéséhez.
  • Kompozíció — a UI Widgetek child/children-en keresztüli beágyazásával épül, öröklődés nélkül, rugalmasságot és újrafelhasználhatóságot biztosítva.
  • BuildContext — a Widget pozíciójának leírója a fában a Theme, Navigator, MediaQuery és InheritedWidget eléréséhez.
  • Teljesítmény — a Widgetek minden buildkor újra létrejönnek (60 FPS), de a RenderObject újrahasznosításra kerül típusegyezés esetén.
  • Kategóriák — a Widgetek layout (Row, Column, Stack), painting (Container, Padding), interactive (GestureDetector, TextField) és platform (MaterialApp, Theme) kategóriákra oszthatók.

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.

Projekt megbeszélése

Olvassa el is