Mobilutveckling med Flutter · Lektion

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.

Lektion 2 av 413 steg

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 ColorScheme som 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 brightness för att få motsvarande ljusa eller mörka variant.
  • Det genererade schemat garanterar korrekt kontrast mellan roller som primary och 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,
);

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 ThemeData fö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.system följer operativsystemets inställning automatiskt.
  • ThemeMode.light / ThemeMode.dark tvingar 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 harmonizeWith på en Color tillsammans 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.primary tillsammans med scheme.onPrimary för framträdande åtgärder.
  • scheme.surface tillsammans med scheme.onSurface för bakgrunder och text.
  • scheme.surfaceContainerHighest fö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.system så 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.platformBrightnessOf nä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.system reagerar.
  • Tvinga tillfälligt fram themeMode: ThemeMode.dark fö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.fromSeed för ljust och mörkt läge när dynamiska färger inte är tillgängliga.
  • Dynamiska färger: DynamicColorBuilder tillhandahåller scheman baserade på bakgrundsbilden, med ?? seedScheme som reservvärde.
  • Harmonisering: blanda varumärkesfärger och anpassade färger mot den dynamiska primärfärgen.
  • Semantiska roller: läs roller från colorScheme i stället för hårdkodade hexadecimala färger, så växlar widgets automatiskt.
  • Lägesstyrning: themeMode: ThemeMode.system som standard, med en valfri växel med ValueNotifier.

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.

Gratis att börja

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

  1. Material 3-färgscheman och startfärger
  2. Dynamiska färger och anpassningsbara ljusa och mörka teman
  3. Anpassad ThemeExtension för varumärkestoken
  4. Responsiv typografi och tematisering av komponenter
← Tillbaka till Mobilutveckling med Flutter