Dynamiska färger och anpassningsbara ljusa och mörka teman
Anpassa färgpaletten efter användarens bakgrundsbild och växla sömlöst mellan ljust och mörkt läge.
Dynamiska färger och anpassningsbara ljusa och mörka teman är en gratis lektion i Mobilutveckling med Flutter på CoddyKit. Detta är lektion 2 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Mobilutveckling med Flutter, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Mobilutveckling med Flutter innehåller totalt 4 lektioner.
Varför dynamisk färg är viktig
Material 3 introducerade dynamisk färg: en apps palett kan härledas från användarens bakgrundsbild (Android 12+), så att gränssnittet känns personligt och inbyggt på enheten.
- På enheter som stöds tillhandahåller systemet ett
ColorSchemesom hämtats från bakgrundsbilden. - På äldre enheter eller andra plattformar använder ni en varumärkesbaserad grundfärg som reserv.
- Samma logik måste generera både ett ljust och ett mörkt schema.
I den här lektionen kopplar ni in dynamisk färg, bygger anpassningsbara ljusa och mörka teman och låter systemet avgöra vilket som ska visas.
Grundfärgen som bas
Även med dynamisk färg behöver ni alltid en reservlösning. Material 3:s ColorScheme.fromSeed genererar en komplett, tillgänglig palett från en enda grundfärg.
- Skicka med
brightnessför att få motsvarande ljusa eller mörka variant. - Det genererade schemat garanterar korrekt kontrast mellan roller som
primaryochonPrimary.
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,
);Bygga ljusa och mörka ThemeData
Ett ThemeData innehåller ett ColorScheme samt typografi och komponentstilar. Med Material 3 anger ni useMaterial3: true och skickar in schemat.
- Skapa ett
ThemeDataför varje ljusstyrka. - Håll dem konsekventa genom att härleda båda från samma grundfärg.
ThemeData buildTheme(ColorScheme scheme) {
return ThemeData(
useMaterial3: true,
colorScheme: scheme,
appBarTheme: AppBarTheme(
backgroundColor: scheme.surface,
foregroundColor: scheme.onSurface,
),
);
}Låta systemet välja läge
MaterialApp tar emot både ett theme (ljust) och ett darkTheme. Egenskapen themeMode avgör vilket som är aktivt.
ThemeMode.systemföljer operativsystemets inställning automatiskt.ThemeMode.light/ThemeMode.darktvingar fram ett läge (praktiskt för en växlare i appen).
Med ThemeMode.system växlar Flutter sömlöst när användaren aktiverar eller inaktiverar mörkt läge i enhetens inställningar.
MaterialApp(
theme: buildTheme(lightScheme),
darkTheme: buildTheme(darkScheme),
themeMode: ThemeMode.system,
home: const HomePage(),
);Läsa dynamisk färg från systemet
Paketet dynamic_color tillhandahåller den bakgrundsbildsbaserade paletten via widgeten DynamicColorBuilder. Dess builder ger er valfria ljusa och mörka ColorScheme-värden.
- Om enheten stöder dynamisk färg är båda schemana skilda från
null. - Om inte är de
null, och ni använder er grundfärg som reserv.
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(),
);
},
);Harmonisera varumärkesfärger
När ni blandar dynamiska färger från bakgrundsbilden med er varumärkesfärg kan de skära sig. Hjälpfunktionerna harmonize förskjuter en anpassad färg mot den dynamiska primary-färgen, så att accenterna känns sammanhållna.
- Använd
harmonizeWithpå enColortillsammans med schemats primärfärg. - På så sätt förblir anpassade semantiska färger (success, warning) förenliga med varumärket och bakgrundsbilden.
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);
}Färgroller, inte hårdkodade hexadecimala färger
För att teman ska kunna anpassas måste widgets läsa semantiska roller från Theme.of(context).colorScheme i stället för hårdkodade färger.
scheme.primarytillsammans medscheme.onPrimaryför framträdande åtgärder.scheme.surfacetillsammans medscheme.onSurfaceför bakgrunder och text.scheme.surfaceContainerHighestför diskreta kort.
Eftersom dessa roller växlar med ljusstyrkan blir era widgets automatiskt oberoende av ljust eller mörkt läge.
Widget buildCard(BuildContext context) {
final scheme = Theme.of(context).colorScheme;
return Container(
color: scheme.surfaceContainerHighest,
child: Text(
'Adaptive',
style: TextStyle(color: scheme.onSurface),
),
);
}Ren Dart: välja schema efter ljusstyrka
Logiken för att välja vilket schema som ska användas är vanlig Dart. Här är en liten körbar modell av reservregeln: föredra det dynamiska schemat och använd annars det som härletts från grundfärgen.
- Detta motsvarar mönstret
lightDynamic ?? lightScheme. - Inga Flutter-widgets behövs – bara urvalsregeln.
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));
}En temaväxlare i appen
Användare vill ofta kunna åsidosätta systemets inställning. Lagra en ThemeMode i state och skicka den till MaterialApp. En ValueNotifier är ett enkelt sätt att bygga om gränssnittet vid ändringar.
- Använd som standard
ThemeMode.systemså att bakgrundsbild och mörkt läge fortfarande tillämpas. - Låt växlaren välja ljust, mörkt eller återgå till systemets inställning.
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(),
);
},
);Reagera på den aktiva ljusstyrkan
I widgets behöver ni ibland veta vilket läge som faktiskt visas (till exempel för att välja en annan illustration). Läs det från det aktiva temat, inte från enheten, eftersom en växlare i appen kan åsidosätta systemets inställning.
Theme.of(context).brightnessåterspeglar det aktiva temat.- Undvik
MediaQuery.platformBrightnessOfnär en växlare kan åsidosätta systemets inställning.
Widget heroImage(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
return Image.asset(
isDark ? 'assets/hero_dark.png' : 'assets/hero_light.png',
);
}Testa båda lägena snabbt
Kontrollera alltid gränssnittet i båda schemana innan ni publicerar appen. Två praktiska vanor:
- Växla mörkt läge i enhetens eller emulatorns inställningar för att bekräfta att
ThemeMode.systemreagerar. - Tvinga tillfälligt fram
themeMode: ThemeMode.darkför att upptäcka hårdkodade färger och text med låg kontrast.
Vanliga buggar är text med hårdkodad Colors.black som försvinner mot en mörk yta eller en anpassad accentfärg som aldrig harmoniserats med den dynamiska paletten.
Snabbkontroll: välja themeMode
Ni vill att appen automatiskt ska matcha användarens bakgrundsbildsbaserade dynamiska färger och följa operativsystemets ljusa eller mörka inställning, samtidigt som en valfri åsidosättning i appen ska kunna läggas till senare. Vilken är den rätta grundkonfigurationen?
Sammanfattning: anpassade Material 3-teman
Ni har byggt en palett som anpassar sig efter både bakgrundsbild och ljusstyrka:
- Reservvärde för seed:
ColorScheme.fromSeedför ljust och mörkt läge när dynamiska färger inte är tillgängliga. - Dynamiska färger:
DynamicColorBuildertillhandahåller scheman baserade på bakgrundsbilden, med?? seedSchemesom reservvärde. - Harmonisering: blanda varumärkesfärger och anpassade färger mot den dynamiska primärfärgen.
- Semantiska roller: läs roller från
colorSchemei stället för hårdkodade hexadecimala färger, så växlar widgets automatiskt. - Lägesstyrning:
themeMode: ThemeMode.systemsom standard, med en valfri växel medValueNotifier.
Anpassa er efter användaren, hantera reservvärden på ett robust sätt och hårdkoda aldrig en färg som ni kan läsa från schemat.
Lär dig Dart med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 22
- Lektioner
- 88
Vanliga frågor
Är lektionen ”Dynamiska färger och anpassningsbara ljusa och mörka teman” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Mobilutveckling med Flutter, inklusive ”Dynamiska färger och anpassningsbara ljusa och mörka teman”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Mobilutveckling med Flutter innehåller totalt 4 lektioner.
Vad lär jag mig i ”Dynamiska färger och anpassningsbara ljusa och mörka teman”?
Anpassa färgpaletten efter användarens bakgrundsbild och växla sömlöst mellan ljust och mörkt läge. Ni övar på Mobilutveckling med Flutter med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Mobilutveckling med Flutter?
Du behöver inga förkunskaper. Utbildningen i Mobilutveckling med Flutter på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.
Hur lång tid tar lektionen ”Dynamiska färger och anpassningsbara ljusa och mörka teman”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Mobilutveckling med Flutter-lektionen?
Ja. Varje Mobilutveckling med Flutter-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Material 3-färgscheman och startfärger
- Dynamiska färger och anpassningsbara ljusa och mörka teman
- Anpassad ThemeExtension för varumärkestoken
- Responsiv typografi och tematisering av komponenter