Crafting a Theme-Toggle Flutter App: Switch Between Light and Dark Modes with Ease
Tags: flutter, programming, ux, tutorial
Published: 2023-11-07 06:53:26

As more users come to expect a customizable viewing experience in their apps, providing a light/dark mode toggle has become a staple in app development. Flutter, with its rich set of widgets and properties, makes this not only possible but pleasantly straightforward. In this post, we'll walk through how to add a theme toggle to your Flutter app, complete with intuitive sun and moon icons.

Let's start by setting the stage with our main function and `DarkLightApp` widget. We launch our app with `runApp(const DarkLightApp())`, which serves as the entry point. Our `DarkLightApp` is a `StatefulWidget` because theme toggling will change the app's state.

```dart
void main() {
  runApp(const DarkLightApp());
}

class DarkLightApp extends StatefulWidget {
  const DarkLightApp({super.key});
  @override
  _DarkLightAppState createState() => _DarkLightAppState();
}
```

Next, we define `_DarkLightAppState` to hold our theme state. We initialize our theme mode to dark with `ThemeMode _themeMode = ThemeMode.dark`.

```dart
class _DarkLightAppState extends State<DarkLightApp> {
  ThemeMode _themeMode = ThemeMode.dark;
  ...
}
```

Our `_toggleTheme` function takes a boolean `isOn` and sets the theme mode to light or dark, depending on the switch's position. This is where `setState` shines, notifying the framework to redraw the widget with the updated theme mode.

```dart
void _toggleTheme(bool isOn) {
  setState(() {
    _themeMode = isOn ? ThemeMode.light : ThemeMode.dark;
  });
}
```

In the `build` method, we craft our `MaterialApp`, which now includes the theme toggling logic. By setting `debugShowCheckedModeBanner` to `false`, we ensure a clean UI without the debug tag.

```dart
@override
Widget build(BuildContext context) {
  return MaterialApp(
    title: 'Dark/Light App',
    debugShowCheckedModeBanner: false,
    ...
  );
}
```

For our themes, we define both `darkTheme` and `theme`. The `darkTheme` uses `Brightness.dark`, while `theme` uses a color scheme seeded with blue for light mode.

```dart
darkTheme: ThemeData(
  brightness: Brightness.dark,
),
theme: ThemeData(
  colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
  useMaterial3: true,
),
```

Now, the star of our UI: the `Scaffold` within `MaterialApp`'s `home`. The `AppBar` not only holds our title but also a `Row` of `Icons` and a `Switch` that control the theme mode.

```dart
home: Scaffold(
  appBar: AppBar(
    title: const Text('Dark/Light App'),
    actions: [
      Icon(Icons.dark_mode),
      Switch(
        value: _themeMode == ThemeMode.light,
        onChanged: _toggleTheme,
      ),
      Icon(Icons.light_mode),
    ],
  ),
  body: const Center(
    child: Text('Hello World'),
  ),
),
```

The `Switch` widget toggles the theme mode and, flanked by the sun (`Icons.light_mode`) and moon (`Icons.dark_mode`) icons, provides a clear visual cue for its function.

By using Flutter's `ThemeData` and `ThemeMode`, we created a seamless way to allow users to switch between light and dark themes. This not only caters to their visual preferences but also can help save battery life on OLED screens and reduce eye strain in low-light conditions.

Implementing a theme toggle in your Flutter app not only enhances the user experience but also showcases the dynamic capabilities of your app. With just a few lines of code, you can give your users the power to choose their preferred theme, making your app more inclusive and user-friendly.

Happy coding!