Padronizando Temas no Flutter com o Uso da Theme Extension

Edson Melo Souza
2 min readMar 29, 2024

--

Tema Extension é um recurso muito importante para padronizar o tema do nosso App Flutter. Por padrão, o Flutter disponibiliza o ThemeData com suas customizações originais, porém você não está limitado a essas propriedades predefinidas. Aí é que entra as ThemeExtensions.

Por exemplo quero criar a minha paleta de cores background e colorText:

class CustomTheme extends ThemeExtension<CustomTheme> {
final Color backgroundColor;
final Color textColor;

const CustomTheme({required this.backgroundColor, required this.textColor});

@override
ThemeExtension<CustomTheme> copyWith({
Color? backgroundColor,
Color? textColor,
}) {
return CustomTheme(
backgroundColor: backgroundColor ?? this.backgroundColor,
textColor: textColor ?? this.textColor,
);
}

@override
ThemeExtension<CustomTheme> lerp(covariant CustomTheme? other, double t) {
return CustomTheme(
backgroundColor: Color.lerp(backgroundColor, other!.backgroundColor, t)!,
textColor: Color.lerp(textColor, other.textColor, t)!,
);
}
}

Aqui é bem simples: você só precisa estender a ThemeExtension passando a sua classe que você criou e definir as suas cores. Por exemplo, eu criei as cores backgroundColor e textColor, porém você poderia adicionar infinitas cores ou de outro tipo que você queira. Depois, é necessário sobrescrever esses dois métodos: copyWith e lerp, como mostrado na imagem. O copyWith é utilizado para a ThemeExtension ser alterada pelo ThemeData as propriedades (que não podem ser alteradas pois são finais), e lerp é utilizado para animar essas propriedades, para o Flutter conseguir animar a transição das propriedades durante a troca de tema.

Codigo completo:

import 'package:flutter/material.dart';

void main() {
runApp(const MyApp());
}

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

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
themeMode: ThemeMode.system,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
extensions: const [
CustomTheme(
backgroundColor: Colors.white,
textColor: Colors.black,
),
],
),
home: const HomePage(),
);
}
}

class HomePage extends StatelessWidget {
const HomePage({
super.key,
});

@override
Widget build(BuildContext context) {
final theme = Theme.of(context).extension<CustomTheme>()!;

return Scaffold(
backgroundColor: theme.backgroundColor,
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(
'Home Page',
style: TextStyle(color: theme.textColor),
),
),
body: Container(
color: theme.backgroundColor,
child: Column(
children: [
Text('Hello World', style: TextStyle(color: theme.textColor)),
],
),
),
);
}
}

class CustomTheme extends ThemeExtension<CustomTheme> {
final Color backgroundColor;
final Color textColor;

const CustomTheme({required this.backgroundColor, required this.textColor});

@override
ThemeExtension<CustomTheme> copyWith({
Color? backgroundColor,
Color? textColor,
}) {
return CustomTheme(
backgroundColor: backgroundColor ?? this.backgroundColor,
textColor: textColor ?? this.textColor,
);
}

@override
ThemeExtension<CustomTheme> lerp(covariant CustomTheme? other, double t) {
return CustomTheme(
backgroundColor: Color.lerp(backgroundColor, other!.backgroundColor, t)!,
textColor: Color.lerp(textColor, other.textColor, t)!,
);
}
}

Obrigado a todos pela leitura! Espero que tenham encontrado o artigo útil. Até mais!

Linkedin: https://www.linkedin.com/in/edson-souza-flutter/
Github: https://github.com/EdsonMello-code

--

--

Edson Melo Souza

Programador Mobile flutter, react native, kotlin para android e typescript. Apaixonado pelas melhores tecnologias do mercado.