Skip to Content
Flutter⚡ Nâng cao🎨 Themes & Styling

Themes và Styling trong Flutter

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

Cách hiện đại để định nghĩa colors:

ThemeData( colorScheme: ColorScheme.fromSeed( seedColor: Colors.blue, brightness: Brightness.light, ), useMaterial3: true, )

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

@override Widget build(BuildContext context) { final theme = Theme.of(context); return Container( color: theme.primaryColor, child: Text( 'Hello', style: theme.textTheme.headlineMedium, ), ); }

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ụng Text('Title', style: Theme.of(context).textTheme.headlineMedium)

5. Custom Fonts

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

ThemeData( fontFamily: 'Roboto', textTheme: TextTheme( bodyLarge: TextStyle(fontFamily: 'Roboto'), ), )

6. Dark Mode

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

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

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

Custom theme properties:

// Định nghĩa extension @immutable class 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 theme ThemeData( extensions: [ AppColors(success: Colors.green, warning: Colors.orange), ], ) // Sử dụng final colors = Theme.of(context).extension<AppColors>()!; Container(color: colors.success)

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.dart MaterialApp( theme: AppTheme.light, darkTheme: AppTheme.dark, )

📝 Tóm tắt

ComponentMục đích
ThemeDataTheme chính
ColorSchemePalette màu
TextThemeTypography
ThemeModeLight/Dark/System
Theme.of(context)Truy cập theme
ThemeExtensionCustom properties
Last updated on