In order to share colors and font styles throughout our app, we can takeadvantage of themes. There are two ways to define themes: App-wide or usingTheme Widgets that define the colors and font styles for a particular part ofour application. In fact, app-wide themes are just Theme Widgets created atthe root of our apps by the MaterialApp!

After we define a Theme, we can use it within our own Widgets. In addition, theMaterial Widgets provided by Flutter will use our Theme to set the backgroundcolors and font styles for AppBars, Buttons, Checkboxes, and more.

Creating an app theme

In order to share a Theme containing colors and font styles across our entireapp, we can provideThemeDatato the MaterialApp constructor.

If no theme is provided, Flutter creates a fallback theme under the hood.

  1. MaterialApp(
  2. title: title,
  3. theme: ThemeData(
  4. // Define the default Brightness and Colors
  5. brightness: Brightness.dark,
  6. primaryColor: Colors.lightBlue[800],
  7. accentColor: Colors.cyan[600],
  8. // Define the default Font Family
  9. fontFamily: 'Montserrat',
  10. // Define the default TextTheme. Use this to specify the default
  11. // text styling for headlines, titles, bodies of text, and more.
  12. textTheme: TextTheme(
  13. headline: TextStyle(fontSize: 72.0, fontWeight: FontWeight.bold),
  14. title: TextStyle(fontSize: 36.0, fontStyle: FontStyle.italic),
  15. body1: TextStyle(fontSize: 14.0, fontFamily: 'Hind'),
  16. ),
  17. )
  18. );

Please see the ThemeDatadocumentation to see all of the colors and fonts you can define.

Themes for part of an application

If we want to override the app-wide theme in part of our application, we canwrap a section of our app in a Theme Widget.

There are two ways to approach this: creating unique ThemeData, orextending the parent theme.

Creating unique ThemeData

If we don’t want to inherit any application colors or font styles, we can createa ThemeData() instance and pass that to the Theme Widget.

  1. Theme(
  2. // Create a unique theme with "ThemeData"
  3. data: ThemeData(
  4. accentColor: Colors.yellow,
  5. ),
  6. child: FloatingActionButton(
  7. onPressed: () {},
  8. child: Icon(Icons.add),
  9. ),
  10. );

Extending the parent theme

Rather than overriding everything, it often makes sense to extend the parenttheme. We can achieve this by using thecopyWithmethod.

  1. Theme(
  2. // Find and Extend the parent theme using "copyWith". Please see the next
  3. // section for more info on `Theme.of`.
  4. data: Theme.of(context).copyWith(accentColor: Colors.yellow),
  5. child: FloatingActionButton(
  6. onPressed: null,
  7. child: Icon(Icons.add),
  8. ),
  9. );

Using a Theme

Now that we’ve defined a theme, we can use it within our Widget build methodsby using the Theme.of(context) function!

Theme.of(context) looks up the Widget tree and return the nearest Themein the tree. If we have a stand-alone Theme defined above our Widget, itreturns that. If not, it returns the App theme.

In fact, the FloatingActionButton uses this exact technique to find theaccentColor!

  1. Container(
  2. color: Theme.of(context).accentColor,
  3. child: Text(
  4. 'Text with a background color',
  5. style: Theme.of(context).textTheme.title,
  6. ),
  7. );

Complete example

  1. import 'package:flutter/foundation.dart';
  2. import 'package:flutter/material.dart';
  3. void main() {
  4. runApp(MyApp());
  5. }
  6. class MyApp extends StatelessWidget {
  7. @override
  8. Widget build(BuildContext context) {
  9. final appName = 'Custom Themes';
  10. return MaterialApp(
  11. title: appName,
  12. theme: ThemeData(
  13. // Define the default Brightness and Colors
  14. brightness: Brightness.dark,
  15. primaryColor: Colors.lightBlue[800],
  16. accentColor: Colors.cyan[600],
  17. // Define the default Font Family
  18. fontFamily: 'Montserrat',
  19. // Define the default TextTheme. Use this to specify the default
  20. // text styling for headlines, titles, bodies of text, and more.
  21. textTheme: TextTheme(
  22. headline: TextStyle(fontSize: 72.0, fontWeight: FontWeight.bold),
  23. title: TextStyle(fontSize: 36.0, fontStyle: FontStyle.italic),
  24. body1: TextStyle(fontSize: 14.0, fontFamily: 'Hind'),
  25. ),
  26. ),
  27. home: MyHomePage(
  28. title: appName,
  29. ),
  30. );
  31. }
  32. }
  33. class MyHomePage extends StatelessWidget {
  34. final String title;
  35. MyHomePage({Key key, @required this.title}) : super(key: key);
  36. @override
  37. Widget build(BuildContext context) {
  38. return Scaffold(
  39. appBar: AppBar(
  40. title: Text(title),
  41. ),
  42. body: Center(
  43. child: Container(
  44. color: Theme.of(context).accentColor,
  45. child: Text(
  46. 'Text with a background color',
  47. style: Theme.of(context).textTheme.title,
  48. ),
  49. ),
  50. ),
  51. floatingActionButton: Theme(
  52. data: Theme.of(context).copyWith(
  53. colorScheme:
  54. Theme.of(context).colorScheme.copyWith(secondary: Colors.yellow),
  55. ),
  56. child: FloatingActionButton(
  57. onPressed: null,
  58. child: Icon(Icons.add),
  59. ),
  60. ),
  61. );
  62. }
  63. }

Themes Demo