How to use theme with Provider on flutter

In our previous section we’ve discussed how we can use a global theme in Flutter and apply that style across the Widget tree. However, there are better ways to do that.

Certainly, using Provider package to pass ThemeData object is one of them.

Moreover, it makes our flutter app more performant.

However, we can use Provider to share a Theme across an entire app in many ways. One of them is to provide a unique ThemeData to the MaterialApp constructor.

In this section, we’ll see how to use class Constructors to pass the provided value or ThemeData object. The next section will show you a more robust and easy way to use Provider in providing ThemeData object with less line of code.

Sharing colors, and a unique font style throughout a Flutter app, is always a great idea. However, using the Provider package to use that ThemeData object across the app, will be more interesting.

Therefore, let’s jump in and start building our global theme in a different way.

Let us create three folders in our lib folder first. Model, View and Controller.

In model, we create a class first.

import 'package:flutter/material.dart';

class GlobalTheme with ChangeNotifier {
  final globalTheme = ThemeData(
    primarySwatch: Colors.deepOrange,
    textTheme: const TextTheme(
      bodyText1: TextStyle(
        fontSize: 22,
      ),
      bodyText2: TextStyle(
        color: Colors.blue,
        fontSize: 18,
        fontWeight: FontWeight.bold,
      ),
      caption: TextStyle(
        fontSize: 16,
        fontWeight: FontWeight.bold,
        fontStyle: FontStyle.italic,
      ),
      headline1: TextStyle(
        color: Colors.deepPurple,
        fontSize: 50,
        fontFamily: 'Allison',
      ),
      headline2: TextStyle(
        color: Colors.deepOrange,
        fontSize: 30,
        fontWeight: FontWeight.bold,
      ),
    ),
    appBarTheme: const AppBarTheme(
      backgroundColor: Colors.amber,
      // This will control the "back" icon
      iconTheme: IconThemeData(color: Colors.red),
      // This will control action icon buttons that locates on the right
      actionsIconTheme: IconThemeData(color: Colors.blue),
      centerTitle: false,
      elevation: 15,
      titleTextStyle: TextStyle(
        color: Colors.deepPurple,
        fontWeight: FontWeight.bold,
        fontFamily: 'Allison',
        fontSize: 40,
      ),
    ),
  );
}

We’ve created a globalTheme property that defines a unique global theme for us, using the ThemeData widget.

Next, we’ll add the dependency in our pubspec.yaml file, so that we can use Provider package to provide that model class object throughout our app.

dependencies:
  cupertino_icons: ^1.0.2
  flutter:
    sdk: flutter
  intl: ^0.17.0
  provider: ^6.0.1

Now, we should keep the Provider above the root folder and use multi provider and ChangeNotifierProvider, so that we can later use other Providers as well.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'model/global_theme.dart';
import 'view/home.dart';

void main() {
  runApp(
    /// Providers are above [Root App] instead of inside it, so that tests
    /// can use [Root App] while mocking the providers
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => GlobalTheme()),
      ],
      child: const Home(),
    ),
  );
}

In our Home widget, we can get the unique and custom ThemeData object using Provider.of(context).

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '/model/global_theme.dart';
import 'home_page.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final ThemeData globalTheme = Provider.of<GlobalTheme>(context).globalTheme;
    return MaterialApp(
      title: 'Flutter Demo',
      theme: globalTheme,
      home: HomePage(
        homeTheme: globalTheme,
      ),
    );
  }
}

Next step is much easier. Just pass the same ThemeData object, to child widgets in the Widget tree through the class constructors.

In fact, app-wide themes are now just ThemeData object provided by the Provider. Once the theme parameter of Material App takes that unique ThemeData object, we can use that across the app. Because Themes widgets created at the root of an app by the MaterialApp can be used anywhere.

Since we’ve defined our custom Theme, we can use it within our own widgets. Flutter’s Material widgets also use our custom Theme to set the background colors and font styles for AppBars, Buttons and more.

Now we’ll pass the custom ThemeData object quite easily and use in our child widget.

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class HomePage extends StatelessWidget {
  final ThemeData homeTheme;
  const HomePage({Key? key, required this.homeTheme}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          'Testing Global Theme with Provider',
          style: homeTheme.appBarTheme.titleTextStyle,
        ),
      ),
      body: HomeBody(
        homeTheme: homeTheme,
      ),
    );
  }
}

class HomeBody extends StatelessWidget {
  final ThemeData homeTheme;
  const HomeBody({Key? key, required this.homeTheme}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    DateTime now = DateTime.now();
    String stringDate = DateFormat('yyyy-MM-dd – kk:mm').format(now);
    return Center(
      child: Column(
        children: [
          Container(
            margin: const EdgeInsets.all(5),
            padding: const EdgeInsets.all(5),
            child: Text(
              'Headline 2 theme style provided by provider',
              style: homeTheme.textTheme.headline2,
            ),
          ),
          Container(
            margin: const EdgeInsets.all(5),
            padding: const EdgeInsets.all(5),
            child: Text(
              'Headline 1 theme style provided by provider',
              style: homeTheme.textTheme.headline1,
            ),
          ),
          Container(
            margin: const EdgeInsets.all(5),
            padding: const EdgeInsets.all(5),
            child: Text(
              'Body Text 2: Here goes some introduction about yourself. Theme by provider.',
              style: homeTheme.textTheme.bodyText2,
            ),
          ),
          Container(
            margin: const EdgeInsets.all(5),
            padding: const EdgeInsets.all(5),
            child: Text(
              'Body Text 1: Here goes some more information regarding your works. Theme by provider.',
              style: homeTheme.textTheme.bodyText1,
            ),
          ),
          Container(
            margin: const EdgeInsets.all(5),
            padding: const EdgeInsets.all(5),
            child: Text(
              'Datetime theme style provided by provider: $stringDate',
              style: homeTheme.textTheme.caption,
            ),
          ),
        ],
      ),
    );
  }
}

As a result, our app uses that custom theme from AppBar to the body.

Theme example Flutter
Theme example Flutter

The full code is available in this GitHub repository.

What Next

Books at Leanpub

Books in Apress

My books at Amazon

GitHub repository

Technical blog

Twitter

Comments

4 responses to “How to use theme with Provider on flutter”

  1. […] But that is not the end of the story. We can use Provider for many purposes, that also includes passing a global style across the flutter app. However, understanding Provider will remain incomplete if we don’t understand the concept of […]

  2. […] Provider is. Provider package in Flutter serves us in many purposes, that also includes passing a global style or data across the flutter app. We can pass the provided value through child […]

  3. […] we’ve used a custom Global ThemeData object with the help of Provider package. Next, we’ve provided the custom theme based on Pink color […]

  4. […] a global pink ThemeData model class, and we’ve also used Provider package to to provide the custom ThemeData object at the root of the Material App […]

Leave a Reply