Mobiele ontwikkeling met Flutter · Les

Material 3-kleurenschema's en seedkleuren

Genereer harmonieuze kleurenschema's vanuit één seedkleur met ColorScheme.fromSeed.

Les 1 van 413 stappen

Material 3-kleurenschema's en seedkleuren is een gratis Mobiele ontwikkeling met Flutter-les op CoddyKit. Dit is les 1 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.

Wat is een kleurenschema in Material 3?

Material 3 (M3) introduceerde een gestructureerd kleurenschema — een verzameling benoemde kleurrollen die je hele app consistent gebruikt. In plaats van ruwe hexwaarden over widgets te verspreiden, definieer je rollen zoals primary, onPrimary, surface en error, waarna Flutter's themasysteem ze automatisch toepast.

  • primary — de merkkleur voor knoppen, FAB's en actieve tabbladen
  • onPrimary — tekst en pictogrammen die boven op primary worden getekend
  • surface — achtergrond van kaarten, bladen en dialoogvensters
  • onSurface — tekst die op oppervlakken wordt getekend
  • error / onError — kleuren voor validatie en waarschuwingen

Elke rol bestaat in een lichte en een donkere variant, zodat je beide thema's met één definitie van het kleurenschema kunt ondersteunen.

Het probleem dat ColorScheme.fromSeed oplost

Voor M3 moesten ontwikkelaars elke kleurrol handmatig kiezen — primary, secondary, tertiary, oppervlakken, containers en hun tegenhangers met 'on'. Dat zijn meer dan 25 waarden, en handmatig de juiste toegankelijke contrastverhoudingen bereiken is foutgevoelig.

ColorScheme.fromSeed lost dit op door één startkleur te accepteren en het algoritme van Google's HCT-kleurruimte (Hue, Chroma, Tone) te gebruiken om automatisch een volledig, harmonieus en volgens WCAG toegankelijk palet te genereren.

  • Eén invoer → meer dan 25 uitvoerrollen
  • Gegarandeerd contrast tussen combinaties van voorgrond en achtergrond
  • Lichte en donkere varianten op basis van dezelfde startkleur
  • Consistent met de ontwerptaal van Material You

Je eerste ColorScheme.fromSeed

ColorScheme.fromSeed gebruiken is eenvoudig. Geef het door aan ThemeData binnen je MaterialApp. Flutter doet de rest.

De parameter seedColor accepteert elke Color — meestal je merkkleur. Flutter leidt daar vervolgens het volledige palet uit af.

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'M3 Theming Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6750A4), // brand purple
        ),
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Color Scheme Demo')),
      body: const Center(child: Text('Hello Material 3')),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.palette),
      ),
    );
  }
}

Licht en donker vanuit dezelfde startkleur

Een van de grootste voordelen van ColorScheme.fromSeed is dat je zowel een licht als een donker thema kunt genereren op basis van dezelfde zaadkleur, zodat de visuele consistentie tussen modi behouden blijft.

Geef de parameter brightness door om tussen beide te wisselen. Flutter past de tinten automatisch aan — donkere thema's gebruiken lichtere tinten van je zaadkleur op donkere oppervlakken.

import 'package:flutter/material.dart';

const Color _brandColor = Color(0xFF00897B); // teal brand

ThemeData lightTheme() => ThemeData(
      colorScheme: ColorScheme.fromSeed(
        seedColor: _brandColor,
        brightness: Brightness.light,
      ),
      useMaterial3: true,
    );

ThemeData darkTheme() => ThemeData(
      colorScheme: ColorScheme.fromSeed(
        seedColor: _brandColor,
        brightness: Brightness.dark,
      ),
      useMaterial3: true,
    );

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: lightTheme(),
      darkTheme: darkTheme(),
      themeMode: ThemeMode.system, // follows device setting
      home: const Scaffold(
        body: Center(child: Text('Adaptive theme')),
      ),
    );
  }
}

Kleurrollen in widgets gebruiken

Zodra je ColorScheme is ingesteld, kun je de rollen overal benaderen via Theme.of(context).colorScheme. Zo blijven je widgets losgekoppeld van hardgecodeerde kleuren en houden ze automatisch rekening met de lichte of donkere modus.

Veelgebruikte rollen in widgets zijn:

  • colorScheme.primary — accentkleur voor interactieve elementen
  • colorScheme.onPrimary — tekst- en pictogramkleur op primaire achtergronden
  • colorScheme.surface — achtergronden van kaarten en dialoogvensters
  • colorScheme.onSurface — standaardtekstkleur
  • colorScheme.error — indicatoren voor fouttoestanden
import 'package:flutter/material.dart';

class StatusBadge extends StatelessWidget {
  final String label;
  final bool isActive;

  const StatusBadge({super.key, required this.label, required this.isActive});

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;

    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
      decoration: BoxDecoration(
        color: isActive ? cs.primaryContainer : cs.surfaceContainerHighest,
        borderRadius: BorderRadius.circular(20),
      ),
      child: Text(
        label,
        style: TextStyle(
          color: isActive ? cs.onPrimaryContainer : cs.onSurfaceVariant,
          fontWeight: FontWeight.w600,
        ),
      ),
    );
  }
}

Containerrollen: primaryContainer en verwante rollen

M3 introduceerde containerrollen — zachtere versies met minder kleurverzadiging van de kernkleuren, bedoeld voor de achtergronden van UI-elementen zoals chips, kaarten en gevulde knoppen.

  • primaryContainer — zachte primaire achtergrond (ideaal voor geselecteerde chips en gevulde tonale knoppen)
  • onPrimaryContainer — tekst boven op primaryContainer
  • secondaryContainer / tertiaryContainer — vergelijkbare rollen voor de secundaire en tertiaire paletten
  • errorContainer — zacht rood voor inline foutmeldingen

Als je containers gebruikt in plaats van primary voor achtergronden, krijg je een duidelijke visuele hiërarchie en blijven de contrastverhoudingen veilig zonder de dekking handmatig aan te passen.

import 'package:flutter/material.dart';

class InfoCard extends StatelessWidget {
  final String title;
  final String body;

  const InfoCard({super.key, required this.title, required this.body});

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;

    return Card(
      color: cs.primaryContainer,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              title,
              style: Theme.of(context).textTheme.titleMedium?.copyWith(
                    color: cs.onPrimaryContainer,
                    fontWeight: FontWeight.bold,
                  ),
            ),
            const SizedBox(height: 8),
            Text(
              body,
              style: TextStyle(color: cs.onPrimaryContainer),
            ),
          ],
        ),
      ),
    );
  }
}

Specifieke rollen overschrijven

Soms komt de algoritmisch gegenereerde kleur voor een specifieke rol niet precies overeen met je merkrichtlijnen. Je kunt afzonderlijke rollen overschrijven met ColorScheme.fromSeed(...).copyWith(...). Zo behoud je alle automatisch gegenereerde rollen, terwijl je specifieke rollen zelf kunt vastleggen.

Dit patroon is handig wanneer je ontwerpsysteem bijvoorbeeld een exacte rode kleur vereist voor error die afwijkt van de kleur die het HCT-algoritme genereert.

import 'package:flutter/material.dart';

ThemeData buildTheme() {
  // Start from seed, then pin specific roles
  final base = ColorScheme.fromSeed(
    seedColor: const Color(0xFF1565C0), // deep blue brand
  );

  return ThemeData(
    colorScheme: base.copyWith(
      // Exact error red from our design system
      error: const Color(0xFFB00020),
      onError: Colors.white,
      // Pin tertiary to our accent orange
      tertiary: const Color(0xFFE65100),
      onTertiary: Colors.white,
    ),
    useMaterial3: true,
  );
}

Dynamische kleuren: aanpassen aan de achtergrondafbeelding

Android 12+ ondersteunt dynamische kleuren — het systeem haalt een zaadkleur uit de achtergrondafbeelding van de gebruiker en past die toe op alle apps. Flutter ondersteunt dit via het pakket dynamic_color.

Het patroon is: probeer het kleurenschema van het systeem te laden; gebruik je eigen zaadkleur als terugvaloptie wanneer dat niet beschikbaar is (op iOS, oudere versies van Android of wanneer de gebruiker geen achtergrondafbeelding heeft ingesteld).

Daardoor voelt je app op ondersteunde apparaten eigen en persoonlijk aan, terwijl hij overal elders consistent blijft.

// pubspec.yaml: dynamic_color: ^1.7.0

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

const Color _fallbackSeed = Color(0xFF6750A4);

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

  @override
  Widget build(BuildContext context) {
    return DynamicColorBuilder(
      builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
        final lightScheme = lightDynamic ??
            ColorScheme.fromSeed(
              seedColor: _fallbackSeed,
              brightness: Brightness.light,
            );

        final darkScheme = darkDynamic ??
            ColorScheme.fromSeed(
              seedColor: _fallbackSeed,
              brightness: Brightness.dark,
            );

        return MaterialApp(
          theme: ThemeData(colorScheme: lightScheme, useMaterial3: true),
          darkTheme: ThemeData(colorScheme: darkScheme, useMaterial3: true),
          themeMode: ThemeMode.system,
          home: const Scaffold(
            body: Center(child: Text('Dynamic Color')),
          ),
        );
      },
    );
  }
}

Je palet bekijken met een raster van kleurstalen

Tijdens de ontwikkeling is het handig om alle belangrijke kleurrollen op het scherm weer te geven, zodat je het gegenereerde palet visueel kunt controleren. Dit foutopsporingsscherm is een snelle manier om contrast en harmonie te controleren voordat je de app publiceert.

Bouw een eenvoudig raster dat rolnamen koppelt aan hun kleuren en de bijbehorende 'on'-rollen, met de actuele ColorScheme uit de context.

import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;

    final roles = [
      ('Primary', cs.primary, cs.onPrimary),
      ('PrimaryContainer', cs.primaryContainer, cs.onPrimaryContainer),
      ('Secondary', cs.secondary, cs.onSecondary),
      ('SecondaryContainer', cs.secondaryContainer, cs.onSecondaryContainer),
      ('Tertiary', cs.tertiary, cs.onTertiary),
      ('Surface', cs.surface, cs.onSurface),
      ('Error', cs.error, cs.onError),
      ('ErrorContainer', cs.errorContainer, cs.onErrorContainer),
    ];

    return Scaffold(
      appBar: AppBar(title: const Text('Color Palette')),
      body: ListView(
        children: roles.map((r) {
          final (name, bg, fg) = r;
          return Container(
            height: 56,
            color: bg,
            alignment: Alignment.centerLeft,
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: Text(name, style: TextStyle(color: fg, fontWeight: FontWeight.w500)),
          );
        }).toList(),
      ),
    );
  }
}

Veelvoorkomende valkuilen bij kleurenschema's

Vermijd deze fouten wanneer je met M3-kleurenschema's werkt:

  • Hexkleuren hard coderen in widgets — Gebruik altijd Theme.of(context).colorScheme.*, zodat widgets reageren op themawijzigingen en de donkere modus.
  • Colors.white / Colors.black rechtstreeks gebruiken — Deze werken niet goed in de donkere modus. Gebruik in plaats daarvan colorScheme.onSurface of colorScheme.surface.
  • useMaterial3: true vergeten — Zonder deze vlag gebruikt Flutter de standaardinstellingen van M2 en worden je M3-kleurrollen mogelijk niet correct toegepast op ingebouwde widgets.
  • primaryColor uit ThemeData gebruiken — Dat is een M2-concept. In M3 lezen alle widgets hun kleuren uit colorScheme. Stel ThemeData.colorScheme in, niet ThemeData.primaryColor.
  • Lichtsterkte en achtergrond niet op elkaar afstemmen — Als je een schema met Brightness.dark genereert en dit combineert met een witte scaffold, wordt de gebruikersinterface onleesbaar.

Alles samenbrengen: een thematische appstructuur

Hier zie je een complete minimale appstructuur met aanbevolen werkwijzen: een kleurenschema op basis van een zaadkleur, ondersteuning voor licht en donker, useMaterial3: true en widgets die rollen uit de context lezen — nergens hardgecodeerde kleuren.

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

const Color _seed = Color(0xFF2E7D32); // forest green brand

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Green Theme',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: _seed,
          brightness: Brightness.light,
        ),
        useMaterial3: true,
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: _seed,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      themeMode: ThemeMode.system,
      home: const HomeScreen(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    return Scaffold(
      backgroundColor: cs.surface,
      appBar: AppBar(
        title: Text('Dashboard', style: TextStyle(color: cs.onPrimary)),
        backgroundColor: cs.primary,
      ),
      body: Center(
        child: FilledButton.icon(
          onPressed: () {},
          icon: const Icon(Icons.eco),
          label: const Text('Go Green'),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        backgroundColor: cs.tertiary,
        foregroundColor: cs.onTertiary,
        child: const Icon(Icons.add),
      ),
    );
  }
}

Korte controle: ColorScheme.fromSeed

Test je begrip van de werking van ColorScheme.fromSeed in Material 3.

Samenvatting van de les: Material 3-kleurenschema's en zaadkleuren

Dit heb je in deze les geleerd:

  • ColorScheme in M3 definieert een volledige set benoemde kleurrollen (primary, surface, error, containers en de bijbehorende 'on'-rollen) die Flutter-widgets automatisch gebruiken.
  • ColorScheme.fromSeed genereert meer dan 25 rollen op basis van één merkkleur met behulp van het HCT-algoritme van Google, voor gegarandeerde harmonie en toegankelijkheid.
  • Geef brightness: Brightness.light of Brightness.dark door om geschikte varianten uit dezelfde zaadkleur te genereren — combineer dit altijd met MaterialApp.darkTheme voor volledige ondersteuning van de donkere modus.
  • Benader rollen in widgets via Theme.of(context).colorScheme — codeer nooit hexwaarden hard in widgetbestanden.
  • Gebruik containerrollen (primaryContainer, onPrimaryContainer) voor de achtergronden van UI-componenten; ze zorgen voor een visuele hiërarchie zonder handmatige aanpassingen van de dekking.
  • Overschrijf afzonderlijke rollen met .copyWith() wanneer een specifieke merkkleur exact moet zijn.
  • Op Android 12+ haalt dynamische kleuren via het pakket dynamic_color de zaadkleur van het systeem op; zorg altijd voor een terugvaloptie voor andere platforms.
  • Stel altijd useMaterial3: true in op ThemeData, zodat ingebouwde widgets het M3-kleurenschema correct gebruiken.
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 “Material 3-kleurenschema's en seedkleuren” gratis?

Ja — je kunt hier op het web alle 3 lessen van het leerpad Mobiele ontwikkeling met Flutter, waaronder “Material 3-kleurenschema's en seedkleuren”, 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 “Material 3-kleurenschema's en seedkleuren”?

Genereer harmonieuze kleurenschema's vanuit één seedkleur met ColorScheme.fromSeed. 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 1 van 4.

Hoe lang duurt de les “Material 3-kleurenschema's en seedkleuren”?

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