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 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.
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 – 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.
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 – 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.
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.
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).
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 – 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 – 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 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.
| Categorie | Belangrijke widgets | Doel |
|---|---|---|
| Layout | Row, Column, Stack, Container, Expanded, Flexible | Positionering en afmetingen van onderliggende elementen |
| Material | Scaffold, AppBar, Card, Drawer, FAB, TabBar | Material Design 3 UI-componenten |
| Cupertino | CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton | iOS-gestileerde componenten |
| Painting | Opacity, ClipRect, Transform, DecoratedBox, BackdropFilter | Visuele effecten en bijsnijden |
| Async | FutureBuilder, StreamBuilder | Asynchroon laden van gegevens met UI-statussen |
| Accessibility | Semantics, MergeSemantics | Semantische markering voor schermlezers |
Veelgestelde vragen
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.
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.
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.
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.
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
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.
Lees ook