Theme och ThemeData — de centrala temamekanismerna i Flutter som gör det möjligt att globalt ställa in färger, typsnitt, mellanrum och komponentstilar för hela applikationen. ThemeData är ett konfigurationsobjekt som skickas till MaterialApp via parametern theme. Enligt officiell Flutter-dokumentation (2026) minskar korrekt konfiguration av ThemeData mängden duplicerad stilkod med 70–80% och säkerställer en enhetlig skärmbild. Det inbyggda arvssystemet gör det möjligt att åsidosätta temat på nivån för enskilda widgetar via Theme.of(context).
Huvudpunkter
ThemeData — klass som innehåller en fullständig beskrivning av den visuella stilen för en Material-applikation. Den skickas till MaterialApp via parametern theme eller darkTheme och ärvs av alla underordnade widgetar. Varje Material Design-widget använder ThemeData för att få sina stilar: knappfärger, AppBar-storlekar, textstilar, kortmarginaler och ikoner.
Grunden för ThemeData är ColorScheme, som definierar primära, sekundära, surface, error och andra färger. Från dessa färger beräknas automatiskt tillstånd (hover, focus, pressed) för alla Material-komponenter. Till exempel använder ElevatedButton primärfärgen för bakgrunden och onPrimary för texten — utan ytterligare konfiguration.
Widgeten Theme — är en InheritedWidget som sprider temat nedåt i widgetträdet. Vilken widget som helst kan hämta det aktuella temat via Theme.of(context) och även skapa ett nytt tema baserat på ett befintligt med åsidosatta värden via Theme.copyWith eller ThemeData.copyWith.
Slutsats: ThemeData — den enda källan till applikationens stilar. Börja utvecklingen med att definiera ThemeData — detta sätter det visuella språket för hela projektet och förhindrar spridda stilar på olika skärmar.
ColorScheme — det centrala elementet för tematisering i Material 3. Det ersätter föråldrade primarySwatch och primaryColor och tillhandahåller en komplett uppsättning färger för alla tillstånd och komponenter.
ColorScheme innehåller 12 basfärger: primary, onPrimary, secondary, onSecondary, surface, onSurface, error, onError, background, onBackground, outline och shadow. För varje färg beräknas automatiskt ljusa och mörka varianter, samt färger för tillstånden hover, focus, pressed och dragged. När endast primary anges genererar ramverket automatiskt de återstående färgerna via ColorScheme.fromSeed.
Metoden ColorScheme.fromSeed (Material 3) tar emot en basfärg seedColor och genererar en fullständigt harmonisk palett baserat på Material Design 3-algoritmen. Detta eliminerar manuellt val av komplementära och analoga färger. Det räcker med att skicka en enda huvudfärg från varumärket, så skapar ColorScheme.fromSeed en sammanhängande palett för hela Material-systemet.
Slutsats: i nya projekt använder du ColorScheme.fromSeed för att generera paletten. För Material 2-kompatibilitet — primarySwatch. ColorScheme är det obligatoriska minimumet för Material 3.
TextTheme — del av ThemeData som definierar textstilar för alla nivåer av rubriker, underrubriker, brödtext och etiketter. Material Design definierar 15 textstilar: headlineLarge, headlineMedium, headlineSmall, titleLarge, titleMedium och andra.
Typografi ställs in antingen via GoogleFonts för automatisk laddning av typsnitt, eller via inbyggd Theme.of(context).textTheme med anpassade TextStyle. GoogleFonts erbjuder hundratals typsnitt via paketet google_fonts, som cachar dem lokalt efter första laddning. Alternativ — bädda in typsnitt i projektets assets via pubspec.yaml.
För adaptiv typografi stöder TextTheme MediaQuery.textScaleFactor — när systemtypsnittet ökas skalas alla textstilar proportionellt. Dessutom kan olika teckenstorlekar ställas in för olika formfaktorer via isTest beroende på MediaQuery.size.width.
Slutsats: definiera TextTheme i ThemeData och använd Theme.of(context).textTheme för alla textelement. Detta säkerställer enhetliga typsnitt och förenklar globala ändringar av typografin.
Theme — InheritedWidget som sprider temat från förälder till barn. Varje underordnad widget kan både läsa det aktuella temat via Theme.of(context) och skapa sin egen kopia med ändringar via ThemeData.copyWith.
Arvsmekanism: om en widget är inslagen i ett Theme med ny data ser alla dess avkomlingar det åsidosatta temat, medan widgetar utanför denna omslag ser det ursprungliga. Detta gör det möjligt att till exempel isolera stilar för en specifik skärm: rubriken använder ett anpassat tema med modifierad AppBarTheme, och resten av applikationen använder standard.
Nesting av Theme kan vara obegränsad. Flutter använder hierarkisk sökning: vid anrop av Theme.of(context) stiger ramverket uppåt i trädet till det första Theme och returnerar dess tema. Om inget Theme hittas — kastas ett undantag. Därför omsluter MaterialApp alltid applikationen i ett Theme.
Slutsats: arv av Theme — en flexibel mekanism för att isolera stilar. Använd åsidosättande av tema för enskilda skärmar utan att duplicera den allmänna konfigurationen.
Dark theme — Flutters inbyggda förmåga att växla mellan ljust och mörkt tema. ThemeData lagras i parametrarna theme (ljust) och darkTheme (mörkt) för MaterialApp. Parametern themeMode hanterar läget: ThemeMode.light (alltid ljust), ThemeMode.dark (alltid mörkt) eller ThemeMode.system (följer systeminställningar).
Vid implementering av mörkt tema behöver du inte skapa alla stilar från grunden. Det räcker att skicka ColorScheme.fromSeed(seedColor, brightness: Brightness.dark) i darkTheme. Ramverket justerar automatiskt färgerna för mörk bakgrund: surface blir mörkgrått, text blir ljus. De övriga subteman (AppBarTheme, CardTheme, BottomNavigationBarTheme) ärvs från den ljusa versionen om de inte uttryckligen åsidosatts.
För mjuka övergångar mellan teman tillhandahåller Flutter animering via AnimatedTheme. När themeMode ändras animeras färger och stilar, vilket skapar en visuellt tilltalande växling. AnimatedTheme använder Duration och Curve för att ställa in animationshastigheten.
Slutsats: mörkt tema implementeras via darkTheme och ColorScheme.fromSeed med brightness: Brightness.dark. Använd ThemeMode.system för att följa användarens systeminställningar.
Exempel 1 — global temakonfiguration via MaterialApp med ColorScheme.fromSeed.
final ThemeData appTheme = ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.indigo,
brightness: Brightness.light,
),
appBarTheme: const AppBarTheme(
centerTitle: true,
elevation: 0,
),
cardTheme: const CardTheme(
elevation: 2,
margin: EdgeInsets.all(8),
),
);
return MaterialApp(
theme: appTheme,
themeMode: ThemeMode.system,
home: const MyHomePage(),
);
I detta exempel skapas ThemeData med Material 3, ett färgschema baserat på indigo och anpassade AppBar- och Card-stilar. useMaterial3 aktiverar det nya Material 3-temasystemet och ColorScheme.fromSeed genererar den fullständiga paletten.
Exempel 2 — åtkomst till temat och åsidosättande för en del av applikationen.
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Column(
children: [
Text(
'Standardrubrik',
style: theme.textTheme.headlineMedium,
),
Theme(
data: theme.copyWith(
colorScheme: theme.colorScheme.copyWith(
primary: Colors.orange,
),
),
child: const SpecialSection(),
),
],
);
}
Det andra exemplet visar användning av Theme.of(context) för att läsa stilar och Theme() med copyWith för att åsidosätta temat i en del av trädet utan att ändra den globala konfigurationen. SpecialSection inuti Theme får orange primärfärg, medan resten av applikationen behåller originalindigo.
Slutsats: det globala temat ställs in i MaterialApp, åtkomst via Theme.of(context), åsidosättande via Theme med copyWith. För Material 3 använder du ColorScheme.fromSeed.
Misstag 1: användning av primarySwatch istället för ColorScheme i Material 3. primarySwatch är föråldrat och stöds inte i Material 3. Vid användning av useMaterial3: true med primarySwatch ger Flutter en varning. Lösning: byt till ColorScheme.fromSeed för palettgenerering.
Misstag 2: hårdkodning av färger i widgets istället för att använda Theme.of(context). Utvecklare skriver Colors.blue direkt i Container istället för primär- eller sekundärfärg från temat. Vid temabyte förblir sådana färger oförändrade, vilket bryter den enhetliga stilen. Lösning: använd alltid Theme.of(context).colorScheme.primary eller andra färger från temat.
Misstag 3: avsaknad av darkTheme. Om applikationen inte definierar darkTheme, när mörkt tema aktiveras på enheten försöker Flutter automatiskt anpassa det ljusa temat, vilket ofta ger ett dåligt resultat. Lösning: skicka alltid darkTheme i MaterialApp, även om mörkt tema inte är en prioritet — detta är viktig UX för användare.
Misstag 4: skapa ett nytt tema vid varje build. Om ThemeData skapas inuti build-metoden skapar varje ombyggnad av widgeten ett nytt temaobjekt, vilket bryter optimeringen av InheritedWidget. Lösning: flytta ThemeData till ett statiskt fält eller const-konstruktor utanför build.
Slutsats: korrekt tematisering kräver ett enhetligt centraliserat tillvägagångssätt. Flytta ThemeData till konstanter, använd färgscheman från temat och definiera alltid båda teman — ljust och mörkt.
Vanliga frågor
ThemeData — konfigurationsdata (färger, typsnitt, stilar). Theme — InheritedWidget som skickar ThemeData nedåt i widgetträdet. Theme.of(context) returnerar ThemeData som det närmaste Theme sprider i det aktuella sammanhanget.
Hantera themeMode i MaterialApp via applikationens tillstånd. Ändra tillståndet från ThemeMode.light till ThemeMode.dark, så bygger Flutter om hela trädet med det nya temat. För mjuk animering använder du AnimatedTheme.
ColorScheme.fromSeed — Material 3-metod som tar emot en basfärg (seedColor) och genererar en fullständigt harmonisk palett: primary, secondary, tertiary, surface, error och deras on-varianter. Gör det möjligt att få ett sammanhängande färgschema från en enda varumärkesfärg.
Via TextTheme inuti ThemeData: ange TextStyle med fontFamily för varje nivå. För Google Fonts använder du paketet google_fonts och skickar fontFamily direkt till TextTheme. För lokala typsnitt — anslut dem via pubspec.yaml i avsnittet fonts.
Ja. Slå in skärmen i ett Theme med åsidosatt data via copyWith. Alla underordnade widgetar inuti detta Theme får de ändrade stilarna, medan resten av applikationen behåller det ursprungliga temat. Detta skapar ingen extra overhead.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också