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](https://i0.wp.com/sanjibsinha.com/wp-content/uploads/2021/11/Theme-example-Flutter.jpg?ssl=1)
The full code is available in this GitHub repository.
Leave a Reply