Active theme switch in flutter
Tags: flutter, beginners, tutorial, productivity
Published: 2024-02-14 07:23:04

Hello fam 👋!

This tutorial shows the easiest way to setup adaptive themes in your flutter applications and instantly change them whenever user requests. Stick till then end for a better grasp at the concept!

## Contents
- Required Packages 📦
- Initialization 🤩
- Theme change page 🎢

### Required Packages 📦
- [hive_flutter](https://pub.dev/packages/hive_flutter)
- [hive](https://pub.dev/packages/hive)
- [flex_color_scheme](https://pub.dev/packages/flex_color_scheme)

### Initialization 🤩
Here we are using the [**flex_color_scheme**](https://pub.dev/packages/flex_color_scheme) package for the themes, you can have your custom ones setup as you like. So the ease of explaining, this package fits the best!

In your `main.dart` file, add the following code. Don't worry, It's well explained below!

```dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // This is important
  await Hive.initFlutter();
  await Hive.openBox('user');
  // Make use the theme key is set!
  if (!Hive.box('user').containsKey('theme')) {
    await Hive.box('user')
        .put('theme', FlexScheme.values.indexOf(FlexScheme.dellGenoa));
  }
  runApp(const App());
}

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

  @override
  AppState createState() => AppState();
}


class AppState extends State<App> {
  @override
  Widget build(BuildContext context) {
    // This is a Widget that auto updates the state when data in the keys that are being watched are changed.
    return ValueListenableBuilder(
      // the box MUST exists, so look at the main function above
      valueListenable: Hive.box('user').listenable(keys: ['theme']),
      builder: (BuildContext context, Box box, Widget? widget) {
        return MaterialApp(
          title: 'FlutterSimplified',
          // I am putting dart theme by default, you cant put that too as a listenable key and change on user request!
          theme: FlexThemeData.dark(
              scheme: FlexScheme.values[box.get('theme')], useMaterial3: true),
          debugShowCheckedModeBanner: false,
          home: const MyHomePage(), // A StatefuleWidget here
        );
      },
    );
  }
}
```

### Theme change page 🎢
Now, let's make a page where user can select the theme they want!<br>
Let's but that in `theme_selector.dart`.

```dart
import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';

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

  @override
  State<ThemeSelector> createState() => _ThemeSelectorState();
}

class _ThemeSelectorState extends State<ThemeSelector> {
  Box box = Hive.box('user');

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          'Imggy',
          style: TextStyle(
            fontWeight: FontWeight.w500,
          ),
        ),
        leading: IconButton(
          icon: const Icon(CupertinoIcons.back),
          onPressed: () => Navigator.pop(context),
        ),
        automaticallyImplyLeading: false,
      ),
      body: ListView.builder(
        itemCount: FlexScheme.values.length,
        itemBuilder: (BuildContext context, int index) {
          return ListTile(
            leading: Icon(
              CupertinoIcons.color_filter,
              color: box.get('theme') == index ? Colors.blue : null,
            ),
            title: Text(FlexScheme.values[index].toString().split('.').last),
            onTap: () {
              box.put('theme', index);
              setState(() {});
              ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
                content: Text('🍨 Theme has been selected!'),
              ));
              Navigator.pop(context);
            },
            trailing:
                box.get('theme') == index ? const Icon(Icons.check) : null,
          );
        },
      ),
    );
  }
}
```

> The output should be something like this ->

{% vimeo 912673637 %}