Material 3-fargeskjemaer og seed-farger
Generer harmoniske fargeskjemaer fra én seed-farge med ColorScheme.fromSeed.
Material 3-fargeskjemaer og seed-farger er en gratis leksjon i Mobilutvikling med Flutter på CoddyKit. Dette er leksjon 1 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Mobilutvikling med Flutter, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Mobilutvikling med Flutter inneholder totalt 4 leksjoner.
Hva er et fargeskjema i Material 3?
Material 3 (M3) introduserte et strukturert fargeskjema – et sett med navngitte fargeroller som hele appen bruker konsekvent. I stedet for å spre rå heksadesimale verdier rundt i widgetene definerer De roller som primary, onPrimary, surface og error, og Flutter bruker dem automatisk gjennom temamotoren.
- primary — merkevarefargen som brukes for knapper, FAB-er og aktive faner
- onPrimary — tekst/ikoner som tegnes oppå primary
- surface — bakgrunn for kort, ark og dialogbokser
- onSurface — tekst som tegnes på overflater
- error / onError — farger for validering og varsler
Hver rolle finnes i både en lys og en mørk variant, slik at De kan støtte begge temaene med én definisjon av fargeskjemaet.
Problemet ColorScheme.fromSeed løser
Før M3 måtte utviklere velge hver fargerolle manuelt – primary, secondary, tertiary, overflater, beholdere og de tilsvarende «on»-variantene. Det er mer enn 25 verdier, og det er lett å gjøre feil når tilgjengelige kontrastforhold skal sikres manuelt.
ColorScheme.fromSeed løser dette ved å ta imot én startfarge og bruke Googles algoritme for HCT-fargerommet (Hue, Chroma, Tone) til å generere en komplett, harmonisk og WCAG-tilgjengelig palett automatisk.
- Én inndata → mer enn 25 utdataroller
- Garantert kontrast mellom par av forgrunn og bakgrunn
- Lyse og mørke varianter fra samme startfarge
- Konsekvent med designspråket Material You
Ditt første ColorScheme.fromSeed
Det er enkelt å bruke ColorScheme.fromSeed. Send det inn i ThemeData i MaterialApp. Flutter ordner resten.
Parameteren seedColor godtar enhver Color – vanligvis merkevarefargen Deres. Flutter utleder deretter hele paletten fra den.
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),
),
);
}
}Lyst og mørkt tema fra samme startfarge
En av de største fordelene med ColorScheme.fromSeed er at De kan generere både et lyst og et mørkt tema fra den samme startfargen, slik at det visuelle uttrykket blir konsekvent på tvers av modusene.
Send inn parameteren brightness for å bytte mellom dem. Flutter justerer tonene automatisk – mørke temaer bruker lysere toner av startfargen på mørke flater.
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')),
),
);
}
}Tilgang til fargeroller i widgets
Når ColorScheme er konfigurert, kan De få tilgang til rollene overalt via Theme.of(context).colorScheme. Da blir widgetene frikoblet fra hardkodede farger, og de følger automatisk lyst eller mørkt modus.
Vanlige roller De kommer til å bruke i widgets:
colorScheme.primary— fremhevingsfarge for interaktive elementercolorScheme.onPrimary— tekst- og ikonfarge på primærbakgrunnercolorScheme.surface— bakgrunner for kort og dialogboksercolorScheme.onSurface— standard tekstfargecolorScheme.error— indikatorer for feiltilstander
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,
),
),
);
}
}Container-roller: primaryContainer og flere
M3 introduserte container-roller – mykere farger med lavere kromatisitet, utformet for bakgrunner til UI-elementer som chips, kort og fylte knapper.
primaryContainer— myk primærbakgrunn (egner seg godt for valgte chips og fylte tonale knapper)onPrimaryContainer— tekst oppå primaryContainersecondaryContainer/tertiaryContainer— tilsvarende roller for sekundær- og tertiærpaletteneerrorContainer— myk rød for innebygde feilmeldinger
Ved å bruke containere i stedet for rå primary til bakgrunner får De et tydelig visuelt hierarki og trygge kontrastforhold uten å måtte justere gjennomsiktigheten manuelt.
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),
),
],
),
),
);
}
}Overstyre bestemte roller
Noen ganger samsvarer ikke den algoritmisk genererte fargen for en bestemt rolle nøyaktig med retningslinjene for merkevaren. De kan overstyre enkeltroller ved å bruke ColorScheme.fromSeed(...).copyWith(...). Da beholdes alle automatisk genererte roller, samtidig som De kan fastsette bestemte roller.
Dette mønsteret er nyttig når designsystemet for eksempel krever en bestemt rødfarge for error som avviker fra den HCT-algoritmen genererer.
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,
);
}Dynamisk farge: Tilpasning til bakgrunnsbildet
Android 12+ støtter Dynamic Color – systemet henter ut en startfarge fra brukerens bakgrunnsbilde og bruker den i alle apper. Flutter støtter dette via pakken dynamic_color.
Mønsteret er: prøv å laste inn systemets fargeskjema, og bruk Deres egen startfarge som reserve hvis det ikke er tilgjengelig (på iOS, eldre Android-versjoner eller når brukeren ikke har angitt et bakgrunnsbilde).
Dette gjør at appen føles innebygd og personlig på støttede enheter, samtidig som den forblir konsekvent overalt ellers.
// 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')),
),
);
},
);
}
}Forhåndsvis paletten med et rutenett av fargeprøver
Under utviklingen er det nyttig å vise alle viktige fargeroller på skjermen, slik at De visuelt kan kontrollere den genererte paletten. Denne feilsøkingsskjermen er en rask måte å kontrollere kontrast og harmoni på før lansering.
Bygg et enkelt rutenett som kobler rollenavn til fargene deres og de tilsvarende «on»-fargene, ved å bruke den aktive ColorScheme fra konteksten.
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(),
),
);
}
}Vanlige fallgruver med fargeskjemaer
Unngå disse feilene når De arbeider med M3-fargeskjemaer:
- Hardkode heksadesimalfarger i widgets — Bruk alltid
Theme.of(context).colorScheme.*, slik at widgetene reagerer på temaendringer og mørkt modus. - Bruk Colors.white / Colors.black direkte — Disse fungerer dårlig i mørkt modus. Bruk heller
colorScheme.onSurfaceellercolorScheme.surface. - Glem
useMaterial3: true— Uten dette flagget bruker Flutter M2-standarder, og M3-fargerollene brukes kanskje ikke riktig av innebygde widgets. - Bruk
primaryColorfra ThemeData — Dette er et M2-konsept. I M3 leser alle widgets fracolorScheme. AngiThemeData.colorScheme, ikkeThemeData.primaryColor. - Uoverensstemmelse mellom lysstyrke og bakgrunn — Hvis De genererer et
Brightness.dark-skjema og kombinerer det med en hvit scaffold, blir brukergrensesnittet uleselig.
Sett alt sammen: Et tematisert appskall
Her er et komplett, minimalt appskall som demonstrerer anbefalte fremgangsmåter: seed-basert fargeskjema, støtte for lyst og mørkt modus, useMaterial3: true og widgets som leser roller fra konteksten – uten hardkodede farger noe sted.
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),
),
);
}
}Hurtigsjekk: ColorScheme.fromSeed
Test forståelsen Deres av hvordan ColorScheme.fromSeed fungerer i Material 3.
Oppsummering av leksjonen: Material 3-fargeskjemaer og startfarger
Dette lærte De i denne leksjonen:
- ColorScheme i M3 definerer et komplett sett med navngitte fargeroller (primary, surface, error, containere og deres «on»-motstykker) som Flutter-widgeter bruker automatisk.
- ColorScheme.fromSeed genererer over 25 roller fra én enkelt merkevarefarge ved hjelp av Googles HCT-algoritme, noe som sikrer harmoni og god tilgjengelighet.
- Send inn
brightness: Brightness.lightellerBrightness.darkfor å generere passende varianter fra den samme startfargen – kombiner alltid dette medMaterialApp.darkThemefor full støtte for mørkt modus. - Få tilgang til roller i widgets via
Theme.of(context).colorScheme– hardkod aldri heksadesimalverdier i widgetfiler. - Bruk container-roller (
primaryContainer,onPrimaryContainer) som bakgrunn for UI-komponenter. De gir et visuelt hierarki uten manuelle justeringer av gjennomsiktigheten. - Overstyr enkeltroller med
.copyWith()når en bestemt merkevarefarge må være nøyaktig. - På Android 12+ henter Dynamic Color via pakken
dynamic_colorut systemets startfarge. Sørg alltid for en reserveverdi på andre plattformer. - Angi alltid
useMaterial3: truepåThemeData, slik at innebygde widgets leser riktig fra M3-fargeskjemaet.
Lær deg Dart med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 22
- Leksjoner
- 88
Ofte stilte spørsmål
Er leksjonen «Material 3-fargeskjemaer og seed-farger» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Mobilutvikling med Flutter, inkludert «Material 3-fargeskjemaer og seed-farger», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Mobilutvikling med Flutter inneholder totalt 4 leksjoner.
Hva lærer jeg i «Material 3-fargeskjemaer og seed-farger»?
Generer harmoniske fargeskjemaer fra én seed-farge med ColorScheme.fromSeed. Du øver på Mobilutvikling med Flutter med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Mobilutvikling med Flutter?
Ingen tidligere erfaring er nødvendig. Mobilutvikling med Flutter på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 1 av 4.
Hvor lang tid tar leksjonen «Material 3-fargeskjemaer og seed-farger»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Mobilutvikling med Flutter-leksjonen?
Ja. Alle Mobilutvikling med Flutter-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Material 3-fargeskjemaer og seed-farger
- Dynamiske farger og adaptive lyse/mørke temaer
- Egendefinert ThemeExtension for merkevaretokens
- Responsiv typografi og tematisering av komponenter