Flutter Advanced Custom Theming: A Beginner-Friendly Guide

Flutter Advanced Custom Theming: A Beginner-Friendly Guide

FlutterPulse

This article was translated specially for the channel FlutterPulseYou'll find lots of interesting things related to Flutter on this channel. Don't hesitate to subscribe!๐Ÿš€

Master advanced custom theming in Flutter using ThemeExtension for dynamic light and dark modes in one simple guide!

The Ultimate Guide to Advanced Custom Theming in Flutter

Introduction

Theming in Flutter is crucial for maintaining a consistent and scalable UI. In this article, we will learn how to create a custom theme using ThemeExtension to manage colors, text styles, and themes efficiently.

Folder Structure

lib/
โ”‚โ”€โ”€ main.dart
โ”‚โ”€โ”€ theme/
โ”‚ โ”œโ”€โ”€ app_colors.dart
โ”‚ โ”œโ”€โ”€ app_color_theme.dart
โ”‚ โ”œโ”€โ”€ app_text_theme.dart
โ”‚ โ”œโ”€โ”€ app_theme.dart
โ”‚ โ”œโ”€โ”€ theme_data_extension.dart
โ”‚โ”€โ”€ utilities/
โ”‚ โ”œโ”€โ”€ constants.dart
  1. Defines Colors

This file defines the base colors used throughout the app.

// theme/app_colors.dart
import 'package:flutter/material.dart';

class AppColors {
static const Color white = Color(0xFFFFFFFF);
static const Color green = Color(0xFF6FD87B);
static const Color black = Color(0xFF323232);
static const Color red = Color(0xFFEA3223);
static const Color gray = Color(0xFFC5C5C5);
static const Color lightGray = Color(0xFFC5C5C5);
static const Color orange = Color(0xFFFF8A00);

}
  • Centralized color management.
  • Easy to update colors for the entire app.

2. Manages Light & Dark Theme Colors

This file extends the theme with color variations for light and dark themes.

// theme/app_color_theme.dart
import 'package:flutter/material.dart';
import 'app_colors.dart';

class AppColorTheme extends ThemeExtension<AppColorTheme> {
final Color white;
final Color green;
final Color black;
final Color red;
final Color gray;
final Color lightGray;
final Color orange;

// Light Theme Colors
AppColorTheme({
this.white = AppColors.white,
this.green = AppColors.green,
this.black = AppColors.black,
this.gray = AppColors.gray,
this.lightGray = AppColors.lightGray,
this.orange = AppColors.orange,
this.red = AppColors.red,
});

// Dark Theme Colors
factory AppColorTheme.dark() {
return AppColorTheme(
white: AppColors.black,
black: AppColors.white,
gray: const Color.fromARGB(255, 46, 21, 21),
lightGray: const Color.fromARGB(255, 79, 64, 64),
);
}

@override
/// To override default color values while using.
ThemeExtension<AppColorTheme> copyWith({
Color? white,
Color? green,
Color? black,
Color? red,
Color? gray,
Color? lightGray,
Color? orange,
}) {
return AppColorTheme(
white: white ?? this.white,
green: green ?? this.green,
black: black ?? this.black,
red: red ?? this.red,
gray: gray ?? this.gray,
lightGray: lightGray ?? this.lightGray,
orange: orange ?? this.orange,
);
}

@override
ThemeExtension<AppColorTheme> lerp(
covariant ThemeExtension<AppColorTheme>? other, double t) {
return this;
}
}
  • Supports light and dark themes
  • Provides flexibility with copyWith() for color customization.

3. Manages Text Styles

This file defines text styles (big text, normal text, small text, etc.).

// theme/app_text_theme.dart
import 'package:flutter/material.dart';
import '../utilities/constants.dart';
import 'app_colors.dart';

abstract class AppTextThemeBaseModel {
TextStyle get bigText;
TextStyle get text;
TextStyle get smallText;
TextStyle get verySmallText;
}

class AppTextTheme extends ThemeExtension<AppTextTheme>
implements AppTextThemeBaseModel {
double bigTextFontSize = 18;
double normalTextFontSize = 16;
double smallTextFontSize = 12;
double verySmallTextFontSize = 8;

@override
TextStyle get bigText => TextStyle(
fontSize: bigTextFontSize,
color: AppColors.black,
fontWeight: FontWeight.normal,
fontFamily: Constants.fontFamily,
);

/// Font Size: 16, Font weight: Normal
@override
TextStyle get text => TextStyle(
fontSize: normalTextFontSize,
color: AppColors.black,
fontWeight: FontWeight.normal,
fontFamily: Constants.fontFamily,
);

@override
TextStyle get smallText => TextStyle(
fontSize: smallTextFontSize,
color: AppColors.black,
fontWeight: FontWeight.w500,
fontFamily: Constants.fontFamily,
);

@override
TextStyle get verySmallText => TextStyle(
fontSize: verySmallTextFontSize,
color: AppColors.black,
fontWeight: FontWeight.normal,
fontFamily: Constants.fontFamily,
);

@override
ThemeExtension<AppTextTheme> copyWith({
double? bigTextFontSize,
double? normalTextFontSize,
double? smallTextFontSize,
double? verySmallTextFontSize,
}) {
return AppTextTheme()
..bigTextFontSize = bigTextFontSize ?? this.bigTextFontSize
..normalTextFontSize = normalTextFontSize ?? this.normalTextFontSize
..smallTextFontSize = smallTextFontSize ?? this.smallTextFontSize
..verySmallTextFontSize =
verySmallTextFontSize ?? this.verySmallTextFontSize;
}

@override
ThemeExtension<AppTextTheme> lerp(
covariant ThemeExtension<AppTextTheme>? other, double t) {
return this;
}
}
  • Defines custom text styles that are easy to update.
  • Keeps typography consistent throughout the app.

4. Combines Colors & Text Styles

This file merges the color and text themes into light and dark themes.

// theme/app_theme.dart
import 'package:flutter/material.dart';
import '../utilities/constants.dart';
import 'app_color_theme.dart';
import 'app_text_theme.dart';

class AppTheme {
static ThemeData lightTheme() => ThemeData(
fontFamily: Constants.fontFamily,
useMaterial3: true,
extensions: [
AppColorTheme(),
AppTextTheme(),
],
);

static ThemeData darkTheme() => ThemeData(
useMaterial3: true,
fontFamily: Constants.fontFamily,
extensions: [
AppColorTheme.dark(),
AppTextTheme(),
],
);
}
  • Combines colors and typography into a single theme.
  • Provides both light and dark themes.

5. Simplifies Theme Access

This file extendsThemeData and BuildContext for easier theme access.

// theme/theme_data_extension.dart
import 'package:flutter/material.dart';
import 'app_color_theme.dart';
import 'app_text_theme.dart';

extension ThemeDataExtension on ThemeData {
AppColorTheme get appColorTheme =>
extension<AppColorTheme>() ?? AppColorTheme();
AppTextTheme get appTextTheme => extension<AppTextTheme>() ?? AppTextTheme();
}

extension ThemeContext on BuildContext {
AppColorTheme get appColorTheme =>
Theme.of(this).extension<AppColorTheme>() ?? AppColorTheme();
AppTextTheme get appTextTheme =>
Theme.of(this).extension<AppTextTheme>() ?? AppTextTheme();
}
  • Allows quick access to colors and text styles using context.

6. Applies Themes in App

Finally, we apply our custom themes in the MaterialApp.

// main.dart
class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
theme: AppTheme.lightTheme(),
darkTheme: AppTheme.darkTheme(),
themeMode: ThemeMode.system,
);
}
}

How to Use in UI?

// Using with Theme class
Text(
"Hello world.",
style: Theme.of(context).appTextTheme.bigText.copyWith(// Access textheme using Theme class
color: Theme.of(context).appColorTheme.black, // Access theme colors using Theme class
),
),

// Using with BuildContext (Easy to access๐Ÿ˜Š)
Text(
"Hello world.",
style: context.appTextTheme.bigText.copyWith( // Access textheme easily using context๐Ÿ˜Š
color: context.appColorTheme.black, // Access theme colors easily using context๐Ÿ˜Š
),
),

๐ŸŽ‰ Conclusion

  • We built a custom theming system for a scalable UI.
  • Supports light and dark mode.
  • Easy access to colors and typography.

๐Ÿš€ Now your Flutter app has an advanced theme setup!

If you found this article useful, please give it a clap ๐Ÿ‘ and leave a comment ๐Ÿ—จ๏ธ to encourage me to write more!

Happy coding ๐Ÿ˜Š!

Report Page