🎨 Themes & Styling
1. ThemeData
Phần tiêu đề “1. ThemeData”Định nghĩa theme cho toàn app:
MaterialApp( theme: ThemeData( primarySwatch: Colors.blue, brightness: Brightness.light, ), darkTheme: ThemeData( brightness: Brightness.dark, ), themeMode: ThemeMode.system, // Theo hệ thống home: MyApp(),)2. ColorScheme
Phần tiêu đề “2. ColorScheme”Cách hiện đại để định nghĩa colors:
ThemeData( colorScheme: ColorScheme.fromSeed( seedColor: Colors.blue, brightness: Brightness.light, ), useMaterial3: true,)Custom ColorScheme
Phần tiêu đề “Custom ColorScheme”ColorScheme( brightness: Brightness.light, primary: Color(0xFF6200EE), onPrimary: Colors.white, secondary: Color(0xFF03DAC6), onSecondary: Colors.black, error: Color(0xFFB00020), onError: Colors.white, surface: Colors.white, onSurface: Colors.black,)3. Sử dụng Theme trong Code
Phần tiêu đề “3. Sử dụng Theme trong Code”@overrideWidget build(BuildContext context) { final theme = Theme.of(context);
return Container( color: theme.primaryColor, child: Text( 'Hello', style: theme.textTheme.headlineMedium, ), );}4. TextTheme
Phần tiêu đề “4. TextTheme”ThemeData( textTheme: TextTheme( displayLarge: TextStyle(fontSize: 57, fontWeight: FontWeight.bold), headlineMedium: TextStyle(fontSize: 28, fontWeight: FontWeight.w600), bodyLarge: TextStyle(fontSize: 16), bodyMedium: TextStyle(fontSize: 14), labelLarge: TextStyle(fontSize: 14, fontWeight: FontWeight.w500), ),)
// Sử dụngText('Title', style: Theme.of(context).textTheme.headlineMedium)5. Custom Fonts
Phần tiêu đề “5. Custom Fonts”Thêm font vào pubspec.yaml
Phần tiêu đề “Thêm font vào pubspec.yaml”flutter: fonts: - family: Roboto fonts: - asset: assets/fonts/Roboto-Regular.ttf - asset: assets/fonts/Roboto-Bold.ttf weight: 700Áp dụng vào theme
Phần tiêu đề “Áp dụng vào theme”ThemeData( fontFamily: 'Roboto', textTheme: TextTheme( bodyLarge: TextStyle(fontFamily: 'Roboto'), ),)6. Dark Mode
Phần tiêu đề “6. Dark Mode”Toggle Dark Mode
Phần tiêu đề “Toggle Dark Mode”class MyApp extends StatefulWidget { @override State<MyApp> createState() => _MyAppState();}
class _MyAppState extends State<MyApp> { ThemeMode _themeMode = ThemeMode.system;
void toggleTheme() { setState(() { _themeMode = _themeMode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light; }); }
@override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData.light(useMaterial3: true), darkTheme: ThemeData.dark(useMaterial3: true), themeMode: _themeMode, home: HomeScreen(onToggleTheme: toggleTheme), ); }}Với Provider
Phần tiêu đề “Với Provider”class ThemeProvider extends ChangeNotifier { ThemeMode _mode = ThemeMode.system;
ThemeMode get mode => _mode;
void toggle() { _mode = _mode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light; notifyListeners(); }}7. Widget-specific Themes
Phần tiêu đề “7. Widget-specific Themes”ThemeData( elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: Colors.blue, foregroundColor: Colors.white, padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), ), cardTheme: CardTheme( elevation: 4, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), appBarTheme: AppBarTheme( backgroundColor: Colors.blue, foregroundColor: Colors.white, elevation: 0, ),)8. Theme Extensions
Phần tiêu đề “8. Theme Extensions”Custom theme properties:
// Định nghĩa extension@immutableclass AppColors extends ThemeExtension<AppColors> { final Color? success; final Color? warning;
const AppColors({this.success, this.warning});
@override ThemeExtension<AppColors> copyWith({Color? success, Color? warning}) { return AppColors( success: success ?? this.success, warning: warning ?? this.warning, ); }
@override ThemeExtension<AppColors> lerp(ThemeExtension<AppColors>? other, double t) { if (other is! AppColors) return this; return AppColors( success: Color.lerp(success, other.success, t), warning: Color.lerp(warning, other.warning, t), ); }}
// Thêm vào themeThemeData( extensions: [ AppColors(success: Colors.green, warning: Colors.orange), ],)
// Sử dụngfinal colors = Theme.of(context).extension<AppColors>()!;Container(color: colors.success)9. Complete Theme Example
Phần tiêu đề “9. Complete Theme Example”class AppTheme { static ThemeData light = ThemeData( useMaterial3: true, colorScheme: ColorScheme.fromSeed( seedColor: Colors.blue, brightness: Brightness.light, ), fontFamily: 'Roboto', appBarTheme: AppBarTheme( centerTitle: true, elevation: 0, ), cardTheme: CardTheme( elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), ), );
static ThemeData dark = ThemeData( useMaterial3: true, colorScheme: ColorScheme.fromSeed( seedColor: Colors.blue, brightness: Brightness.dark, ), fontFamily: 'Roboto', // ... same widget themes );}
// main.dartMaterialApp( theme: AppTheme.light, darkTheme: AppTheme.dark,)📝 Tóm tắt
Phần tiêu đề “📝 Tóm tắt”| Component | Mục đích |
|---|---|
ThemeData |
Theme chính |
ColorScheme |
Palette màu |
TextTheme |
Typography |
ThemeMode |
Light/Dark/System |
Theme.of(context) |
Truy cập theme |
ThemeExtension |
Custom properties |