Mobiele ontwikkeling met Flutter · Les

Dynamische kleuren en adaptieve lichte/donkere thema's

Pas uw kleurenpalet aan de achtergrond van de gebruiker aan en schakel naadloos tussen lichte en donkere modi.

Les 2 van 413 stappen

Dynamische kleuren en adaptieve lichte/donkere thema's is een gratis Mobiele ontwikkeling met Flutter-les op CoddyKit. Dit is les 2 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Mobiele ontwikkeling met Flutter. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Mobiele ontwikkeling met Flutter bevat in totaal 4 lessen.

Waarom dynamische kleuren belangrijk zijn

Material 3 introduceerde dynamische kleuren: het palet van een app kan worden afgeleid van de achtergrondafbeelding van de gebruiker (Android 12+), zodat je gebruikersinterface persoonlijk aanvoelt en past bij het apparaat.

  • Op ondersteunde apparaten stelt het systeem een ColorScheme beschikbaar dat afkomstig is van de achtergrondafbeelding.
  • Op oudere apparaten of andere platforms gebruik je als terugvaloptie een zaadkleur van het merk.
  • Dezelfde logica moet zowel een licht als een donker schema opleveren.

In deze les verbind je dynamische kleuren, bouw je aanpasbare lichte en donkere thema's en laat je het systeem bepalen welk thema wordt weergegeven.

De zaadkleur als basis

Ook met dynamische kleuren heb je altijd een terugvaloptie nodig. ColorScheme.fromSeed van Material 3 genereert een volledig en toegankelijk palet op basis van één zaadkleur.

  • Geef brightness door om de bijbehorende lichte of donkere variant te krijgen.
  • Het gegenereerde schema garandeert correct contrast tussen rollen zoals primary en onPrimary.
import 'package:flutter/material.dart';

final ColorScheme lightScheme = ColorScheme.fromSeed(
  seedColor: const Color(0xFF6750A4),
  brightness: Brightness.light,
);

final ColorScheme darkScheme = ColorScheme.fromSeed(
  seedColor: const Color(0xFF6750A4),
  brightness: Brightness.dark,
);

Lichte en donkere ThemeData bouwen

Een ThemeData omvat een ColorScheme plus typografie en stijlen voor componenten. Met Material 3 stel je useMaterial3: true in en geef je het schema door.

  • Maak één ThemeData per lichtsterkte.
  • Houd ze consistent door beide uit dezelfde zaadkleur af te leiden.
ThemeData buildTheme(ColorScheme scheme) {
  return ThemeData(
    useMaterial3: true,
    colorScheme: scheme,
    appBarTheme: AppBarTheme(
      backgroundColor: scheme.surface,
      foregroundColor: scheme.onSurface,
    ),
  );
}

Het systeem de modus laten kiezen

MaterialApp accepteert zowel een theme (licht) als een darkTheme. De eigenschap themeMode bepaalt welke actief is.

  • ThemeMode.system volgt automatisch de instelling van het besturingssysteem.
  • ThemeMode.light / ThemeMode.dark forceren een modus (handig voor een schakelaar in de app).

Met ThemeMode.system schakelt Flutter naadloos over wanneer de gebruiker de donkere modus wijzigt in de apparaatinstellingen.

MaterialApp(
  theme: buildTheme(lightScheme),
  darkTheme: buildTheme(darkScheme),
  themeMode: ThemeMode.system,
  home: const HomePage(),
);

Dynamische kleuren van het systeem lezen

Het pakket dynamic_color stelt het palet op basis van de achtergrondafbeelding beschikbaar via de widget DynamicColorBuilder. De builder geeft je optionele lichte en donkere ColorSchemes.

  • Als het apparaat dynamische kleuren ondersteunt, zijn beide schema's niet-null.
  • Als dat niet zo is, zijn ze null en gebruik je je zaadkleur als terugvaloptie.
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';

DynamicColorBuilder(
  builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
    final light = lightDynamic ?? lightScheme;
    final dark = darkDynamic ?? darkScheme;
    return MaterialApp(
      theme: buildTheme(light),
      darkTheme: buildTheme(dark),
      themeMode: ThemeMode.system,
      home: const HomePage(),
    );
  },
);

Merkkleuren harmoniseren

Wanneer je dynamische kleuren van de achtergrondafbeelding combineert met je merkkleur, kunnen de twee botsen. De helpers harmonize verschuiven een aangepaste kleur richting de dynamische primary, zodat accenten samenhangend aanvoelen.

  • Gebruik harmonizeWith op een Color ten opzichte van de primaire kleur van het schema.
  • Zo blijven aangepaste semantische kleuren (succes, waarschuwing) afgestemd op je merk en de achtergrondafbeelding.
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';

ColorScheme harmonizeScheme(ColorScheme scheme) {
  return scheme.harmonized();
}

Color harmonizeBrand(Color brand, ColorScheme scheme) {
  return brand.harmonizeWith(scheme.primary);
}

Kleurrollen, geen hardgecodeerde hexwaarden

Om thema's te kunnen aanpassen, moeten widgets semantische rollen lezen uit Theme.of(context).colorScheme in plaats van hardgecodeerde kleuren te gebruiken.

  • scheme.primary met scheme.onPrimary voor prominente acties.
  • scheme.surface met scheme.onSurface voor achtergronden en tekst.
  • scheme.surfaceContainerHighest voor subtiele kaarten.

Omdat deze rollen met de lichtsterkte wisselen, zijn je widgets automatisch onafhankelijk van de lichte of donkere modus.

Widget buildCard(BuildContext context) {
  final scheme = Theme.of(context).colorScheme;
  return Container(
    color: scheme.surfaceContainerHighest,
    child: Text(
      'Adaptive',
      style: TextStyle(color: scheme.onSurface),
    ),
  );
}

Pure Dart: een schema kiezen op basis van lichtsterkte

De beslislogica voor het schema dat je gebruikt, is gewone Dart-code. Hier is een klein, uitvoerbaar model van de terugvalregel: geef de voorkeur aan het dynamische schema en gebruik anders het uit de zaadkleur afgeleide schema.

  • Dit weerspiegelt het patroon lightDynamic ?? lightScheme.
  • Je hebt geen Flutter-widgets nodig — alleen de selectieregel.
enum Brightness { light, dark }

String chooseScheme({
  required Brightness brightness,
  required bool supportsDynamic,
}) {
  final base = supportsDynamic ? 'dynamic' : 'seed';
  return '$base-${brightness.name}';
}

void main() {
  print(chooseScheme(brightness: Brightness.dark, supportsDynamic: true));
  print(chooseScheme(brightness: Brightness.light, supportsDynamic: false));
}

Een themaschakelaar in de app

Gebruikers willen het systeem vaak kunnen overschrijven. Bewaar een ThemeMode in de status en geef die door aan MaterialApp. Een ValueNotifier is een lichte manier om bij wijzigingen opnieuw op te bouwen.

  • Gebruik standaard ThemeMode.system, zodat de achtergrondafbeelding en de donkere modus van toepassing blijven.
  • Laat de schakelaar licht, donker of weer de systeeminstelling kiezen.
final themeModeNotifier = ValueNotifier<ThemeMode>(ThemeMode.system);

ValueListenableBuilder<ThemeMode>(
  valueListenable: themeModeNotifier,
  builder: (context, mode, _) {
    return MaterialApp(
      theme: buildTheme(lightScheme),
      darkTheme: buildTheme(darkScheme),
      themeMode: mode,
      home: const HomePage(),
    );
  },
);

Reageren op de effectieve lichtsterkte

Binnen widgets moet je soms weten welke modus daadwerkelijk wordt weergegeven (bijvoorbeeld om een andere illustratie te kiezen). Lees dit uit het actieve thema, niet van het apparaat, omdat een schakelaar in de app de systeeminstelling kan overschrijven.

  • Theme.of(context).brightness geeft het opgeloste thema weer.
  • Vermijd MediaQuery.platformBrightnessOf wanneer een schakelaar de instelling kan overschrijven.
Widget heroImage(BuildContext context) {
  final isDark = Theme.of(context).brightness == Brightness.dark;
  return Image.asset(
    isDark ? 'assets/hero_dark.png' : 'assets/hero_light.png',
  );
}

Beide modi snel testen

Controleer je gebruikersinterface altijd in beide schema's voordat je de app publiceert. Twee praktische gewoonten:

  • Schakel de donkere modus in via de instellingen van het apparaat of de emulator om te controleren of ThemeMode.system reageert.
  • Forceer tijdelijk themeMode: ThemeMode.dark om hardgecodeerde kleuren en tekst met een laag contrast te vinden.

Veelvoorkomende fouten zijn tekst met een hardgecodeerde Colors.black die verdwijnt op een donker oppervlak, of een aangepast accent dat nooit met het dynamische palet is geharmoniseerd.

Korte controle: themeMode kiezen

Je wilt dat je app automatisch de dynamische kleuren op basis van de achtergrondafbeelding van de gebruiker overneemt én de lichte of donkere instelling van het besturingssysteem volgt, terwijl je later nog steeds een optionele overschrijving in de app wilt toestaan. Wat is de juiste basisconfiguratie?

Samenvatting: adaptieve Material 3-thema's

Je hebt een palet gemaakt dat zich aanpast aan zowel de achtergrondafbeelding als de helderheid:

  • Fallback voor de startkleur: ColorScheme.fromSeed voor licht en donker wanneer dynamische kleuren niet beschikbaar zijn.
  • Dynamische kleuren: DynamicColorBuilder levert paletten op basis van de achtergrondafbeelding, met ?? seedScheme als fallback.
  • Harmonisatie: meng merk- en aangepaste kleuren richting de dynamische primaire kleur.
  • Semantische rollen: lees rollen uit colorScheme in plaats van hardgecodeerde hexwaarden, zodat widgets automatisch omschakelen.
  • Modusbeheer: standaard themeMode: ThemeMode.system, met optioneel een schakelaar via ValueNotifier.

Pas je aan de gebruiker aan, val netjes terug en hardcode nooit een kleur die je uit het kleurenschema kunt lezen.

Gratis beginnen

Leer Dart met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
22
Lessen
88

Veelgestelde vragen

Is de les “Dynamische kleuren en adaptieve lichte/donkere thema's” gratis?

Ja — je kunt hier op het web alle 3 lessen van het leerpad Mobiele ontwikkeling met Flutter, waaronder “Dynamische kleuren en adaptieve lichte/donkere thema's”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Mobiele ontwikkeling met Flutter bevat in totaal 4 lessen.

Wat leer ik in “Dynamische kleuren en adaptieve lichte/donkere thema's”?

Pas uw kleurenpalet aan de achtergrond van de gebruiker aan en schakel naadloos tussen lichte en donkere modi. Je oefent met Mobiele ontwikkeling met Flutter door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Mobiele ontwikkeling met Flutter te beginnen?

Ervaring vooraf is niet nodig. Mobiele ontwikkeling met Flutter op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.

Hoe lang duurt de les “Dynamische kleuren en adaptieve lichte/donkere thema's”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Mobiele ontwikkeling met Flutter?

Ja. Elke les over Mobiele ontwikkeling met Flutter bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Material 3-kleurenschema's en seedkleuren
  2. Dynamische kleuren en adaptieve lichte/donkere thema's
  3. Aangepaste ThemeExtension voor merkketens
  4. Responsieve typografie en thematisering van componenten
← Terug naar Mobiele ontwikkeling met Flutter