Flutter Widgets — wat is het, widgetboom en build

Auteur: IT Sectr Gepubliceerd: 2026-02-21 Leestijd: 8 min

Flutter Widgets – de basisbouwstenen van de gebruikersinterface in het Google Flutter-framework, uitgebracht in stabiele versie 1.0 in december 2018. In Flutter is alles een widget: van scherm en knop tot ruimte en uitlijning. Widgets vormen een boom (widget tree) die Flutter rendert op zijn eigen Skia/Impeller-engine, waarbij native platformcomponenten worden omzeild. Volgens Google I/O (2025) wordt Flutter gebruikt in meer dan 500.000 apps in Google Play en App Store. De Flutter-architectuur verdeelt widgets in StatelessWidget (onveranderlijk) en StatefulWidget (met veranderlijke toestand via het State-object).

Belangrijkste

  • Flutter Widgets – alle UI-elementen in Flutter: van scherm en knop tot ruimte en uitlijning; het framework gebruikt geen native platformcomponenten.
  • StatelessWidget – widget zonder veranderlijke toestand; toont via de constructor doorgegeven gegevens en verandert niet na de build.
  • StatefulWidget – widget met veranderlijke toestand, opgeslagen in een apart State-object dat rebuilds overleeft.
  • Widgetboom (widget tree) – hiërarchie van widgets die de UI beschrijven; Flutter zet dit om in Element Tree en Render Tree voor rendering.
  • BuildContext – de buildcontext, die toegang biedt tot de positie van de widget in de boom, het thema, MediaQuery en InheritedWidget.

Wat zijn Flutter Widgets?

Flutter Widgets – alle UI-elementen in het Flutter-framework, geïmplementeerd als onveranderlijke (immutable) Dart-klassen. Een widget is een configuratie van een UI-element: de grootte, kleur, positie en gebeurtenisafhandeling. In tegenstelling tot Android (XML + View) of iOS (Storyboard + UIView) gebruikt Flutter geen native componenten – alles wordt getekend door de Skia-engine (Android/iOS/Linux) of Impeller (iOS/macOS) op Canvas. Dit zorgt voor een identiek uiterlijk op alle platforms zonder platformverschillen. Flutter wordt geleverd met twee widgetsets: Material Widgets (Google Material Design 3 voor Android/Web) en Cupertino Widgets (Apple HIG voor iOS/macOS). De ontwikkelaar kan beide sets in één app combineren. Elke widget heeft een build()-methode die een kind-widget of een compositie daarvan retourneert – zo wordt de widgetboom opgebouwd.

De drie Flutter-bomen

Flutter werkt met drie bomen: Widget Tree (configuratie, gemaakt door de ontwikkelaar), Element Tree (koppeling van widget aan positie in de boom, beheerd door het framework), Render Tree (objecten die layout berekenen en paint uitvoeren). Widget creëert Element, dat RenderObject creëert. Element wordt herbruikt bij configuratiewijziging (rebuild) – dit is het optimalisatiemechanisme van Flutter: als het widgettype en de key overeenkomen, wordt Element niet opnieuw aangemaakt, maar wordt alleen de nieuwe configuratie bijgewerkt. Inzicht in de drie bomen is de sleutel tot het optimaliseren van de prestaties van Flutter-apps.

StatelessWidget: onveranderlijke widgets

StatelessWidget – een widget die geen interne toestand opslaat. Het ontvangt parameters via de constructor en toont ze zonder wijzigingsmogelijkheid na de build. StatelessWidget is ideaal voor statische elementen: titels, pictogrammen, avatars, lijsten met vaste gegevens. De build()-methode wordt eenmaal aangeroepen bij het maken en bij wijziging van de bovenliggende widget. Omdat StatelessWidget geen toestand heeft, heeft het geen apart State-object nodig – build() is direct in de widgetklasse gedefinieerd.

dart
import 'package:flutter/material.dart';

class ProfileHeader extends StatelessWidget {
  final String name;
  final String avatarUrl;

  const ProfileHeader({super.key, required this.name, required this.avatarUrl});

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        CircleAvatar(
          radius: 24,
          backgroundImage: NetworkImage(avatarUrl),
        ),
        const SizedBox(width: 12),
        Text(
          name,
          style: const TextStyle(
            fontSize: 18,
            fontWeight: FontWeight.bold,
          ),
        ),
      ],
    );
  }
}

ProfileHeader – een StatelessWidget dat name en avatarUrl via de constructor ontvangt. CircleAvatar toont de avatar, Text de naam. De widget kan deze waarden na creatie niet wijzigen. Het gebruik van de const-constructor (const ProfileHeader) stelt Flutter in staat om de widgetinstantie te herbruiken bij rebuild van de ouder – dit is een micro-optimalisatie die voor alle StatelessWidgets wordt aanbevolen.

StatefulWidget: widgets met toestand

StatefulWidget – een widget met veranderlijke toestand, opgeslagen in een apart State-object. StatefulWidget zelf is onveranderlijk (immutable), net als StatelessWidget. Het veranderlijke deel is ondergebracht in State: State – een object dat eenmaal wordt gemaakt en meerdere rebuilds van de widget overleeft. Wanneer de toestand verandert (setState()), roept Flutter de build() van State aan en werkt de UI bij. StatefulWidget wordt gebruikt voor interactieve elementen: tellers, tekstvelden, selectievakjes, animaties, timers.

dart
import 'package:flutter/material.dart';

class LikeButton extends StatefulWidget {
  const LikeButton({super.key});

  @override
  State<LikeButton> createState() => _LikeButtonState();
}

class _LikeButtonState extends State<LikeButton> {
  bool liked = false;
  int count = 42;

  void _toggleLike() {
    setState(() {
      liked = !liked;
      count += liked ? 1 : -1;
    });
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: _toggleLike,
      child: Text(liked ? '♥ $count' : '♡ $count'),
    );
  }
}

LikeButton – een StatefulWidget met de State-klasse _LikeButtonState. De velden liked en count zijn toestand die in State wordt opgeslagen en niet wordt gereset bij rebuild. setState() stelt Flutter op de hoogte van de noodzaak om de UI te herbouwen. Flutter maakt State niet opnieuw bij elke ouder-rebuild – alleen bij configuratiewijziging (key of widgettype). Bij IT Sectr gebruiken we StatelessWidget voor weergave en StatefulWidget voor interactieve componenten, volgens het principe van het minimaliseren van StatefulWidget tot aan de mutatiegrenzen.

Widgetboom: van Widget tot RenderObject

Widget Tree – de hiërarchische structuur van widgets die de UI van de app beschrijft. Flutter zet Widget Tree om in Element Tree: elke Widget creëert een Element dat de positie in de boom en de verbinding met RenderObject bijhoudt. Render Tree voert layout (bepalen van afmetingen en posities) en paint (tekenen) uit. Element is de cruciale optimalisatielaag: als het widgettype en de key niet zijn veranderd bij rebuild, wordt Element herbruikt, waarbij de configuratie wordt bijgewerkt zonder RenderObject opnieuw aan te maken. Dit zorgt voor Flutter-prestaties bij een hoge framesnelheid (60/120 FPS).

dart
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter Widgets')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.flutter_dash, size: 80),
            const SizedBox(height: 16),
            const Text(
              'Hallo, Flutter!',
              style: TextStyle(fontSize: 24),
            ),
          ],
        ),
      ),
    );
  }
}

De widgetboom van HomeScreen: Scaffold → AppBar + Center → Column → [Icon, SizedBox, Text]. Scaffold – de belangrijkste layoutwidget van Material Design. Center centreert de kind-Column. Column rangschikt kinderen verticaal met uitlijning in het midden (mainAxisAlignment.center). Flutter berekent de layout van boven naar beneden (constraints worden doorgegeven van de ouder) en afmetingen van beneden naar boven (sizedByParent of sizing from children).

BuildContext: buildcontext en toegang tot de boom

BuildContext – een descriptor van de positie van de widget in de Element Tree. Elke build()-methode ontvangt BuildContext, waarmee de widget toegang krijgt tot:MediaQuery (schermgrootte, oriëntatie, pixeldichtheid, veilig gebied), Theme (MaterialThemeData of CupertinoThemeData), Navigator (navigatiestack), ScaffoldMessenger (SnackBar), InheritedWidget (doorgeven van gegevens langs de boom). BuildContext mag niet worden bewaard na het voltooien van build() of worden gebruikt buiten een synchrone context – dit leidt tot fouten zoals „Scaffold.of() called with a context that does not contain a Scaffold”. Gebruik in plaats van context op te slaan de Builder-widget of het InheritedWidget-patroon voor toegang tot gegevens.

Key: identificatie van de widget in de boom

Key – een optionele parameter van de constructor van elke widget (super.key). Key helpt Flutter bij het identificeren van de widget bij wijziging van de volgorde/het aantal elementen in een lijst. Zonder key vergelijkt Flutter widgets op type en positie; bij het toevoegen van een element in het midden van een lijst zonder key hergebruikt Flutter Element voor de verkeerde widget, wat status- (StatefulWidget) en animatiefouten veroorzaakt. Gebruik ValueKey (unieke identificatie) voor lijsten, ObjectKey (op basis van het gegevensobject), UniqueKey (gegarandeerd uniek bij elke rebuild – voor geforceerde herbouw).

Flutter-widgetcatalogus: Material, Cupertino, Layout

Flutter SDK (stabiele versie 3.3+, Dart 3+) bevat 200+ ingebouwde widgets, verdeeld in categorieën: Layout (Row, Column, Stack, Container, Expanded, Flexible, Wrap, GridView, ListView, CustomScrollView), Material Design (Scaffold, AppBar, Card, Drawer, BottomNavigationBar, FloatingActionButton, TabBar, Chip, DataTable), Cupertino (CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton, CupertinoTabBar), Painting & Effects (Opacity, DecoratedBox, ClipRect, Transform, BackdropFilter, ShaderMask), Async (FutureBuilder, StreamBuilder) en Accessibility (Semantics, MergeSemantics, ExcludeSemantics). Layout-widgets vormen de basis van elke Flutter-UI: Row voor horizontale reeksen, Column voor verticale, Stack voor overlappende elementen, Container met BoxDecoration voor decoratie.

CategorieBelangrijke widgetsDoel
LayoutRow, Column, Stack, Container, Expanded, FlexiblePositionering en afmetingen van onderliggende elementen
MaterialScaffold, AppBar, Card, Drawer, FAB, TabBarMaterial Design 3 UI-componenten
CupertinoCupertinoPageScaffold, CupertinoNavigationBar, CupertinoButtoniOS-gestileerde componenten
PaintingOpacity, ClipRect, Transform, DecoratedBox, BackdropFilterVisuele effecten en bijsnijden
AsyncFutureBuilder, StreamBuilderAsynchroon laden van gegevens met UI-statussen
AccessibilitySemantics, MergeSemanticsSemantische markering voor schermlezers

Veelgestelde vragen

Waarin verschilt StatelessWidget van StatefulWidget?

StatelessWidget heeft geen interne toestand – alle gegevens worden via de constructor doorgegeven en veranderen niet. StatefulWidget slaat de veranderlijke toestand op in een apart State-object dat rebuilds overleeft. Toestandsverandering roept setState() aan en Flutter herbouwt de UI. Gebruik StatelessWidget voor onveranderlijke elementen; StatefulWidget voor interactieve.

Wat is BuildContext in Flutter?

BuildContext – een descriptor van de positie van de widget in de Element Tree, doorgegeven aan de build()-methode. Via context heeft de widget toegang tot MediaQuery, Theme, Navigator, ScaffoldMessenger en InheritedWidget. BuildContext mag niet worden bewaard na het voltooien van build(). Gebruik voor toegang tot gegevens de Builder-widget of InheritedWidget.

Moet ik Dart kennen om met Flutter te werken?

Ja, Flutter gebruikt Dart als enige programmeertaal. Dart is een statisch getypeerde taal met null-safety, sound types, extension methods en pattern matching. Om te beginnen zijn de basisbeginselen van Dart voldoende: klassen, functies, async/await, collecties. Dart wordt gecompileerd naar native code (AOT) via Dart Native en naar JavaScript (voor het web) via Dart2JS.

Is Flutter alleen voor mobiele platforms?

Nee, Flutter ondersteunt zes platforms: iOS, Android, Web, macOS, Windows, Linux. Meer dan 90% van de code is gemeenschappelijk voor alle platforms. Platformaanpassingen (camera, bestandssysteem) worden gerealiseerd via plug-ins of platformkanalen. Voor desktop gebruikt Flutter de Flutter Desktop-vensteromhulling, voor het web de CanvasKit-engine (WebGL) of de HTML-renderer.

Hoe zorgt Flutter voor prestaties van 60 FPS?

Flutter bereikt 60/120 FPS dankzij: zijn eigen 2D-engine (Skia/Impeller), de afwezigheid van een native bridge (in tegenstelling tot React Native), drie bomen (Widget → Element → Render) met herbruik van Element bij ongewijzigd type/key, een layout-algoritme met eenrichtingsdoorloop (constraints down, sizes up) en RepaintBoundary voor het isoleren van het opnieuw tekenen van afzonderlijke schermzones.

Samenvatting

  • Flutter Widgets – alle UI-elementen: van Scaffold tot SizedBox; Flutter tekent ze zelf op Skia/Impeller, zonder native componenten te gebruiken.
  • StatelessWidget – widget zonder toestand; build() retourneert UI op basis van de onveranderlijke constructorparameters.
  • StatefulWidget – widget met veranderlijke toestand in State; setState() veroorzaakt UI-rebuild.
  • Drie bomen Flutter: Widget (configuratie) → Element (positie) → Render (layout + paint); Element wordt herbruikt voor prestaties.
  • BuildContext – positie van de widget in de boom; toegang tot MediaQuery, Theme, Navigator, InheritedWidget.
  • Material en Cupertino – twee widgetsets voor respectievelijk Google Material Design 3 en Apple HIG.
  • Key (ValueKey, ObjectKey, UniqueKey) – identificatie van de widget bij wijziging van volgorde/aantal in de lijst.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook