Padronizando Temas no Flutter com o Uso da Theme Extension
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