Themes

In Flutter, a theme is a set of pre-defined colors, fonts, and other design properties that can be applied to an entire app or specific widgets within the app.
The main benefit of using themes is that they provide a consistent and visually appealing appearance throughout the app.
XFlutter-CLI tool comes with 2 main themes (Light Theme/Dark Theme) with ability to switch current theme with Theme Notifier.

Initialize Theme:

To share a Theme across your entire app, set the theme property to your MaterialApp constructor
void main() async {
  // initialize app dependencies
  await configureAppDependencies(environment: environment);
  runApp(const MyApp());
}

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

  @override
  State<MyApp> createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    final themeMode = GetIt.instance<ThemeNotifier>(); // current ThemeMode from theme_notifier.dart
    return MaterialApp(
      theme: lightTheme, // from theme.dart
      darkTheme: darkTheme, // from dark_theme.dart
      themeMode: themeMode,
      // ...
    );
  }
}

Change Current Theme:

To switch Light/Dark theme you can call `toggleThemeMode` from `ThemeNotifier`
class MyWidget extends StatelessWidget {
  const MyWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return TextButton(
      onPressed: () {
        final ThemeNotifier themeNotifier = GetIt.instance<ThemeNotifier>();
        themeNotifier.toggleThemeMode();
      },
      child: const Text('Change Theme'),
    );
  }
}

Detect Current Theme Changes:

You can handle switching current theme with 2 options:

1. LiveDataBuilder

Wrap Your MaterialApp with LiveDataBuilder:
class MyAppState extends State<MyApp> {

  @override
  Widget build(BuildContext context) {
    return LiveDataBuilder<ThemeMode>( // add LiveDataBuilder here
      data: GetIt.instance<ThemeNotifier>().themeMode,
      builder: (context, themeMode) => MaterialApp.router(
        routerDelegate: appRouter.delegate(),
        routeInformationParser: appRouter.defaultRouteParser(),
        theme: lightTheme,
        darkTheme: darkTheme,
        themeMode: themeMode,
        locale: context.locale,
        debugShowCheckedModeBanner: false,
        supportedLocales: context.supportedLocales,
        localizationsDelegates: context.localizationDelegates,
      ),
    );
  }
}
When ThemeNotifier changes the current theme, the LiveDataBuilder will re-build the MaterialApp with new theme.

2. Event Driven:

You can listen for changes with `EventBus`:
import 'events/event_bus.dart';

class MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();

    // change Material-App current theme
    eventBus.on<ThemeChangedEvent>().listen((_) {
        // handle changes
    });
  } 
}