Flutter set theme from a list

Flutter set theme from a list

I am trying to add a list of theme that user can chose one here is my list

import 'package:flutter/material.dart';

class ThemeModel {
  final Color surface;
  final Color primary;
  final Color secondary;
  final Color onSurface;

  ThemeModel({
    required this.surface,
    required this.primary,
    required this.secondary,
    required this.onSurface,
  });
}

final List<ThemeModel> themes = [
  ThemeModel(
    surface: Color(0xFFF0EAD6),
    primary: Color(0xFF6C9A8B),
    secondary: Color(0xFFA67C52),
    onSurface: Color(0xFF3B3A36),
  ),
  ThemeModel(
    surface: Color(0xFFF5F5F5),
    primary: Color(0xFF6D6875),
    secondary: Color(0xFFFFB4A2),
    onSurface: Color(0xFF2D2D2D),
  ),
  ThemeModel(
    surface: Color(0xFFF0F8FF),
    primary: Color(0xFFA2C7E5),
    secondary: Color(0xFF89B0AE),
    onSurface: Color(0xFF2F3E46),
  ),
];

I'll show a list and they can chose one that will save a number like chosenTheme now i have a ThemeData like this

ThemeData myTheme = ThemeData(
  fontFamily: 'estedad',
  useMaterial3: true,
  //brightness: chosenTheme <= 2 ? Brightness.light : Brightness.dark,
  colorScheme:
      chosenTheme <= 2
          ? ColorScheme.light(
            surface: cards[chosenTheme].themes.surface,
            primary: cards[chosenTheme].themes.primary,
            secondary: cards[chosenTheme].themes.secondary,
            onSurface: cards[chosenTheme].themes.onSurface,
          )
          : ColorScheme.dark(
            surface: cards[chosenTheme].themes.surface,
            primary: cards[chosenTheme].themes.primary,
            secondary: cards[chosenTheme].themes.secondary,
            onSurface: cards[chosenTheme].themes.onSurface,
          ),
);

how can i set this as apps default theme in a theme provider?

Answer

Create a ThemeProvider class:

import 'package:provider/provider.dart';

class ThemeProvider with ChangeNotifier {
  int _chosenTheme = 0; // default theme

  int get chosenTheme => _chosenTheme;

  set chosenTheme(int value) {
    _chosenTheme = value;
    notifyListeners();
  }

  ThemeData get themeData {
    final theme = themes[_chosenTheme]; // import themes list

    return ThemeData(
      fontFamily: 'estedad',
      useMaterial3: true,
      colorScheme:
          _chosenTheme <= 2
              ? ColorScheme.light(
                surface: theme.surface,
                primary: theme.primary,
                secondary: theme.secondary,
                onSurface: theme.onSurface,
              )
              : ColorScheme.dark(
                surface: theme.surface,
                primary: theme.primary,
                secondary: theme.secondary,
                onSurface: theme.onSurface,
              ),
    );
  }
}

Use ThemeProvider's Consumer inside MyApp Widget and provide themeData to MaterialApp:

import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Consumer<ThemeProvider>(
      builder: (context, themeProvider, _) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Themed App',
          theme: themeProvider.themeData,
          home: const HomeScreen(),
        );
      },
    );
  }
}

Create a List to update selected theme:

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

  @override
  Widget build(BuildContext context) {
    final themeProvider = Provider.of<ThemeProvider>(context);

    return Scaffold(
      appBar: AppBar(title: const Text("Choose a Theme")),
      body: ListView.builder(
        itemCount: themes.length,
        itemBuilder: (context, index) {
          final theme = themes[index];
          return ListTile(
            title: Text("Theme ${index + 1}"),
            tileColor: theme.surface,
            textColor: theme.onSurface,
            onTap: () {
              themeProvider.chosenTheme = index;
            },
          );
        },
      ),
    );
  }
}

Now, Whenever theme is updated by the user it will update the widget tree with the new themeData. Use SharedPreferences to persist the chosenTheme in ThemeProvider.

Enjoyed this article?

Check out more content on our blog or follow us on social media.

Browse more articles