Theme și ThemeData — mecanismele centrale de tematizare în Flutter, care permit setarea culorilor, fonturilor, spațierilor și stilurilor componentelor la nivel global pentru întreaga aplicație. ThemeData este un obiect de configurare transmis în MaterialApp prin parametrul theme. Conform documentației oficiale Flutter (2026), configurarea corectă a ThemeData reduce cantitatea de cod de stilizare duplicat cu 70–80% și asigură un aspect uniform al ecranelor. Sistemul încorporat de moștenire permite redefinirea temei la nivelul widgeturilor individuale prin Theme.of(context).
Principalele puncte
ThemeData — clasă care conține descrierea completă a stilului vizual al aplicației Material. Se transmite în MaterialApp prin parametrul theme sau darkTheme și este moștenită de toate widgeturile copil. Fiecare widget Material Design folosește ThemeData pentru a-și obține stilurile: culorile butoanelor, dimensiunile AppBar, stilurile textului, spațierile cardurilor și pictogramele.
La baza ThemeData stă ColorScheme, care definește culorile primary, secondary, surface, error și altele. Din aceste culori se calculează automat stările (hover, focus, pressed) pentru toate componentele Material. De exemplu, ElevatedButton folosește culoarea primary pentru fundal și onPrimary pentru text — fără configurare suplimentară.
Widgetul Theme — este un InheritedWidget care răspândește tema în josul arborelui de widgeturi. Orice widget poate obține tema curentă prin Theme.of(context) și poate crea o temă nouă pe baza celei existente cu valori redefinite prin Theme.copyWith sau ThemeData.copyWith.
Concluzie: ThemeData — sursa unică de stiluri a aplicației. Începeți dezvoltarea cu definirea ThemeData — acesta stabilește limbajul vizual al întregului proiect și previne stilurile disparate în diferite ecrane.
ColorScheme — elementul central al tematizării în Material 3. Înlocuiește primarySwatch și primaryColor învechite, oferind un set complet de culori pentru toate stările și componentele.
ColorScheme conține 12 culori de bază: primary, onPrimary, secondary, onSecondary, surface, onSurface, error, onError, background, onBackground, outline și shadow. Pentru fiecare culoare se calculează automat variantele light și dark, precum și culorile pentru stările hover, focus, pressed și dragged. La specificarea doar a culorii primary, framework-ul generează restul culorilor automat prin ColorScheme.fromSeed.
Metoda ColorScheme.fromSeed (Material 3) primește o culoare de bază seedColor și generează o paletă armonioasă completă pe baza algoritmului Material Design 3. Aceasta elimină selectarea manuală a culorilor complementary și analogous. Este suficient să transmiteți o culoare principală a mărcii, iar ColorScheme.fromSeed va crea o paletă coerentă pentru întregul sistem Material.
Concluzie: în proiecte noi utilizați ColorScheme.fromSeed pentru generarea paletei. Pentru compatibilitatea cu Material 2 — primarySwatch. ColorScheme este minimul obligatoriu pentru Material 3.
TextTheme — partea din ThemeData care definește stilurile textului pentru toate nivelurile de titluri, subtitluri, corp și etichete. Material Design definește 15 stiluri de text: headlineLarge, headlineMedium, headlineSmall, titleLarge, titleMedium și altele.
Tipografia se setează fie prin GoogleFonts pentru încărcarea automată a fonturilor, fie prin Theme.of(context).textTheme încorporat cu TextStyle-uri personalizate. GoogleFonts oferă sute de fonturi prin pachetul google_fonts, care le stochează în cache local după prima încărcare. Alternativa — încorporarea fonturilor în assets-urile proiectului prin pubspec.yaml.
Pentru tipografie adaptivă, TextTheme suportă MediaQuery.textScaleFactor — la mărirea fontului de sistem, toate stilurile de text se scalează proporțional. Suplimentar, se pot seta dimensiuni diferite ale fontului pentru diferite formate prin isTest în funcție de MediaQuery.size.width.
Concluzie: definiți TextTheme în ThemeData și folosiți Theme.of(context).textTheme pentru toate elementele text. Aceasta asigură uniformitatea fonturilor și simplifică modificările globale ale tipografiei.
Theme — InheritedWidget care răspândește tema de la părinte la copii. Orice widget copil poate atât citi tema curentă prin Theme.of(context), cât și crea propria copie cu modificări prin ThemeData.copyWith.
Mecanismul de moștenire: dacă un widget este înfășurat într-un Theme cu date noi, toți descendenții săi văd tema redefinită, iar widgeturile din afara acestei înfășurări — tema originală. Aceasta permite, de exemplu, izolarea stilurilor pentru un ecran specific: titlul folosește o temă personalizată cu AppBarTheme modificat, iar restul aplicației — tema standard.
Încastrarea Theme poate fi nelimitată. Flutter folosește căutarea ierarhică: la apelul Theme.of(context), framework-ul urcă în susul arborelui până la primul Theme și returnează tema acestuia. Dacă nu se găsește niciun Theme — se aruncă o excepție. De aceea MaterialApp înfășoară întotdeauna aplicația într-un Theme.
Concluzie: moștenirea Theme — un mecanism flexibil pentru izolarea stilurilor. Utilizați redefinirea temei pentru ecrane individuale fără a duplica configurația generală.
Dark theme — capacitatea încorporată a Flutter de a comuta între tema luminoasă și cea întunecată. ThemeData este stocată în parametrii theme (luminoasă) și darkTheme (întunecată) ai MaterialApp. Parametrul themeMode gestionează modul: ThemeMode.light (întotdeauna luminoasă), ThemeMode.dark (întotdeauna întunecată) sau ThemeMode.system (urmează setările sistemului).
La implementarea temei întunecate nu este necesar să creați toate stilurile de la zero. Este suficient să transmiteți ColorScheme.fromSeed(seedColor, brightness: Brightness.dark) în darkTheme. Framework-ul ajustează automat culorile pentru fundal întunecat: surface devine gri-închis, textul — deschis. Celelalte subteme (AppBarTheme, CardTheme, BottomNavigationBarTheme) se moștenesc din versiunea luminoasă, dacă nu sunt redefinite explicit.
Pentru tranziția lină între teme, Flutter oferă animație prin AnimatedTheme. La schimbarea themeMode, culorile și stilurile sunt animate, creând o comutare vizual plăcută. AnimatedTheme folosește Duration și Curve pentru setarea vitezei de animație.
Concluzie: dark theme se implementează prin darkTheme și ColorScheme.fromSeed cu brightness: Brightness.dark. Folosiți ThemeMode.system pentru a urmări setările de sistem ale utilizatorului.
Exemplul 1 — configurarea globală a temei prin MaterialApp folosind 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(),
);
În acest exemplu se creează ThemeData cu Material 3, schema de culori bazată pe indigo și stiluri personalizate AppBar și Card. useMaterial3 activează noul sistem de teme Material 3, iar ColorScheme.fromSeed generează paleta completă.
Exemplul 2 — accesul la temă și redefinirea pentru o parte a aplicației.
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Column(
children: [
Text(
'Titlu standard',
style: theme.textTheme.headlineMedium,
),
Theme(
data: theme.copyWith(
colorScheme: theme.colorScheme.copyWith(
primary: Colors.orange,
),
),
child: const SpecialSection(),
),
],
);
}
Al doilea exemplu arată utilizarea Theme.of(context) pentru citirea stilurilor și Theme() cu copyWith pentru redefinirea temei într-o parte a arborelui fără a modifica configurația globală. SpecialSection în interiorul Theme va primi culoarea primary portocalie, restul aplicației — indigo original.
Concluzie: tema globală se setează în MaterialApp, accesul prin Theme.of(context), redefinirea prin Theme cu copyWith. Pentru Material 3 utilizați ColorScheme.fromSeed.
Eroarea 1: utilizarea primarySwatch în loc de ColorScheme în Material 3. primarySwatch este învechit și nu este suportat în Material 3. La utilizarea useMaterial3: true cu primarySwatch, Flutter afișează un avertisment. Soluție: treceți la ColorScheme.fromSeed pentru generarea paletei.
Eroarea 2: setarea rigidă a culorilor în widgeturi în loc să folosiți Theme.of(context). Dezvoltatorii scriu Colors.blue direct în Container în loc de culoarea primary sau secondary din temă. La schimbarea temei, aceste culori rămân neschimbate, încălcând stilul unitar. Soluție: folosiți întotdeauna Theme.of(context).colorScheme.primary sau alte culori din temă.
Eroarea 3: lipsa darkTheme. Dacă aplicația nu definește darkTheme, la activarea temei întunecate pe dispozitiv, Flutter încearcă să adapteze tema luminoasă automat, ceea ce dă adesea un rezultat de calitate scăzută. Soluție: transmiteți întotdeauna darkTheme în MaterialApp, chiar dacă tema întunecată nu este o prioritate — acesta este un UX important pentru utilizatori.
Eroarea 4: crearea unei teme noi la fiecare build. Dacă ThemeData este creat în interiorul metodei build, fiecare reconstruire a widgetului creează un obiect temă nou, stricând optimizarea InheritedWidget. Soluție: mutați ThemeData într-un câmp static sau constructor const în afara build.
Concluzie: tematizarea corectă necesită o abordare centralizată unitară. Mutați ThemeData în constante, folosiți schemele de culori din temă și definiți întotdeauna ambele teme — luminoasă și întunecată.
Întrebări frecvente
ThemeData — sunt datele de configurare (culori, fonturi, stiluri). Theme — InheritedWidget care transmite ThemeData în josul arborelui de widgeturi. Theme.of(context) returnează ThemeData pe care cel mai apropiat Theme îl răspândește în contextul curent.
Gestionați themeMode în MaterialApp prin starea aplicației. Schimbați starea din ThemeMode.light în ThemeMode.dark, iar Flutter va reconstrui întregul arbore cu noua temă. Pentru animație lină utilizați AnimatedTheme.
ColorScheme.fromSeed — metoda Material 3 care primește o culoare de bază (seedColor) și generează o paletă armonioasă completă: primary, secondary, tertiary, surface, error și variantele lor on. Permite obținerea unei scheme de culori coerente dintr-o singură culoare a mărcii.
Prin TextTheme în interiorul ThemeData: specificați TextStyle cu fontFamily pentru fiecare nivel. Pentru Google Fonts utilizați pachetul google_fonts, transmițând fontFamily direct în TextTheme. Pentru fonturi locale — conectați-le prin pubspec.yaml în secțiunea fonts.
Da. Înfășurați ecranul într-un Theme cu date redefinite prin copyWith. Toate widgeturile copil din interiorul acestui Theme vor primi stilurile modificate, iar restul aplicației va păstra tema originală. Acest lucru nu creează costuri suplimentare.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și