Material 3-kleurenschema's en seedkleuren
Genereer harmonieuze kleurenschema's vanuit één seedkleur met ColorScheme.fromSeed.
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 elementencolorScheme.onPrimary— tekst- en pictogramkleur op primaire achtergrondencolorScheme.surface— achtergronden van kaarten en dialoogvensterscolorScheme.onSurface— standaardtekstkleurcolorScheme.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 primaryContainersecondaryContainer/tertiaryContainer— vergelijkbare rollen voor de secundaire en tertiaire palettenerrorContainer— 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.onSurfaceofcolorScheme.surface. useMaterial3: truevergeten — Zonder deze vlag gebruikt Flutter de standaardinstellingen van M2 en worden je M3-kleurrollen mogelijk niet correct toegepast op ingebouwde widgets.primaryColoruit ThemeData gebruiken — Dat is een M2-concept. In M3 lezen alle widgets hun kleuren uitcolorScheme. StelThemeData.colorSchemein, nietThemeData.primaryColor.- Lichtsterkte en achtergrond niet op elkaar afstemmen — Als je een schema met
Brightness.darkgenereert 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.lightofBrightness.darkdoor om geschikte varianten uit dezelfde zaadkleur te genereren — combineer dit altijd metMaterialApp.darkThemevoor 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_colorde zaadkleur van het systeem op; zorg altijd voor een terugvaloptie voor andere platforms. - Stel altijd
useMaterial3: truein opThemeData, zodat ingebouwde widgets het M3-kleurenschema correct gebruiken.
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
- Material 3-kleurenschema's en seedkleuren
- Dynamische kleuren en adaptieve lichte/donkere thema's
- Aangepaste ThemeExtension voor merkketens
- Responsieve typografie en thematisering van componenten