What is a theme in Flutter?

A theme in Flutter is an integral part of the user interface. Moreover, it is an extended part of Material design.

In this article, we’ll try to understand how we can use theme to design color, and font to make our flutter app more visually good-looking.

Firstly, we can define our global theme in the MaterialApp widget.

In our previous articles, we’ve seen how we can influence the child widgets through MaterialApp. We could’ve done that because MaterialApp is the parent widget and maintains the material design principles.

Therefore, we can apply the same logic in our theme also.

Subsequently, we can define our global theme in the MaterialApp widget.

Before we delve into detail, let me tell you that we keep the full code snippet in this GitHub Repository.

Firstly, let us take a look at the MaterialApp theme definition.

import 'package:flutter/material.dart';
import 'default_page.dart';
import 'first_page.dart';
import 'home_page.dart';
import 'second_page.dart';

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Daily News',
      theme: ThemeData(
        primarySwatch: Colors.brown,
        primaryColor: Colors.blue,
        canvasColor: const Color.fromRGBO(255, 254, 229, 1),
        textTheme: ThemeData.light().textTheme.copyWith(
              bodyText2: const TextStyle(
                color: Color.fromRGBO(0, 155, 0, 1.0),
                fontSize: 30,
                fontWeight: FontWeight.bold,
                //fontFamily: 'Allison',
              ),
              bodyText1: const TextStyle(
                color: Color.fromRGBO(20, 51, 51, 1),
                fontSize: 30,
                fontWeight: FontWeight.bold,
              ),
              headline6: const TextStyle(
                fontSize: 20,
                fontWeight: FontWeight.bold,
              ),
            ),
      ),
      // home: CategoriesScreen(),
      initialRoute: '/', // default is '/'
      routes: {
        '/': (ctx) => const HomePage(),
        FirstPage.routename: (ctx) => const FirstPage(),
        SecondPage.routename: (ctx) => const SecondPage(),
      },
      onUnknownRoute: (settings) {
        return MaterialPageRoute(
          builder: (ctx) => const DefaultPage(),
        );
      },
    );
  }
}

Since we’ve defined our theme in MaterialApp widget, we can apply that theme globally with the help of Theme.of method.

Through this method we can pass the context and moreover, we can select what type of text style we need to adopt.

Let us take a close look at the theme property.

theme: ThemeData(
        primarySwatch: Colors.brown,
        primaryColor: Colors.blue,
        canvasColor: const Color.fromRGBO(255, 254, 229, 1),
        textTheme: ThemeData.light().textTheme.copyWith(
              bodyText2: const TextStyle(
                color: Color.fromRGBO(0, 155, 0, 1.0),
                fontSize: 30,
                fontWeight: FontWeight.bold,
                fontFamily: 'Allison',
              ),
              bodyText1: const TextStyle(
                color: Color.fromRGBO(20, 51, 51, 1),
                fontSize: 30,
                fontWeight: FontWeight.bold,
              ),
              headline6: const TextStyle(
                fontSize: 20,
                fontWeight: FontWeight.bold,
              ),
            ),
      ),

The theme property of MaterialApp widget returns ThemeData constructor. Consequently, we can define many things. The primary color, font, different text style, etc.

When we apply this theme, the primary variant makes the same text color darker. We’ll see that in a minute. Before that, we need to know more about Flutter theme.

How do you give a theme on Flutter?

As we’ve said, we share colors and font styles throughout a flutter app. That’s why we define ThemeData to the MaterialApp constructor.

When we provide ThemeData to the MaterialApp constructor theme property, we can use that theme app wide.

Moreover, when we defina a Theme, we can use it within our own widgets as well as we can set the background colors and font styles for AppBars, Buttons, Checkboxes, and moreTo share a Theme across an entire app.

As a result, we can provide that theme to the immediate child, home page.

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

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);
  static const routename = '/first';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Home Page'),
      ),
      body: Column(
        children: [
          Container(
            margin: const EdgeInsets.all(10.0),
            padding: const EdgeInsets.all(10.0),
            child: GestureDetector(
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => const FirstPage()),
                );
              },
              child: ClipRRect(
                borderRadius: const BorderRadius.only(
                  topLeft: Radius.circular(15.0),
                  topRight: Radius.circular(15.0),
                  bottomLeft: Radius.circular(15.0),
                  bottomRight: Radius.circular(15.0),
                ),
                child: Image.network(
                    'https://cdn.pixabay.com/photo/2020/05/15/14/03/lake-5173683_960_720.jpg'),
              ),
            ),
          ),
          const SizedBox(
            height: 10,
          ),
          Text(
            'Material App Home First',
            style: TextStyle(
              color: Theme.of(context).colorScheme.primary,
              fontSize: 30,
            ),
          ),
          const SizedBox(
            height: 10,
          ),
          Text(
            'Material App Home Second',
            style: TextStyle(
              color: Theme.of(context).colorScheme.primaryVariant,
              fontSize: 20,
              fontWeight: FontWeight.bold,
            ),
          ),
          const SizedBox(
            height: 10,
          ),
          Text(
            'Material App Home Third',
            style: Theme.of(context).textTheme.bodyText1,
          ),
          const SizedBox(Text(
            'Material App Home Third',
            style: Theme.of(context).textTheme.bodyText1,
          ),
            height: 10,
          ),
          Text(
            'Material App Home Fourth',
            style: Theme.of(context).textTheme.bodyText2,
          ),
        ],
      ),
    );
  }
}

Inside home page, now, after the image there are four text widgets, which use different text styles defined in MaterialApp.

Material Theme flutter example
Material Theme flutter example

Now, if we add a special font “Allison” to a certain text style defined in MaterialApp theme property, it changes its look.

However, we need to create a “font” folder inside the “lib” folder of our app, and then we need to add the dependencies in our “pubspec.yaml” file.

# To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  fonts:
  
    - family: Allison
      fonts:
        - asset: lib/fonts/Allison-Regular.ttf

As a result, that special font reflects in our flutter app.

Material Theme flutter with font home page
Material Theme flutter with font home page

We’ve declared the font in this way in MaterialApp theme property. The font family property of text style widget points to the “Allison” font.

Subsequently, each text that follows this text style will display text in that font.

bodyText2: const TextStyle(
                color: Color.fromRGBO(0, 155, 0, 1.0),
                fontSize: 30,
                fontWeight: FontWeight.bold,
                fontFamily: 'Allison',
              ),

After that, we’ve declared that in our home page code:

Text(
            'Material App Home Third',
            style: Theme.of(context).textTheme.bodyText2,
          ),

As a result, each text style that uses “bodyText2” style displays the text in that font only.

How do I change the text theme in Flutter?

To change the text theme in Flutter, we can follow another method. We’ll see that in another page, that is first page.

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

class FirstPage extends StatelessWidget {
  const FirstPage({Key? key}) : super(key: key);
  static const routename = '/first';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('First Page'),
      ),
      body: GestureDetector(
        onTap: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const SecondPage()),
          );
        },
        child: Column(
          children: [
            Container(
              margin: const EdgeInsets.all(10.0),
              padding: const EdgeInsets.all(10.0),
              child: ClipRRect(
                borderRadius: const BorderRadius.only(
                  topLeft: Radius.circular(15.0),
                  topRight: Radius.circular(15.0),
                  bottomLeft: Radius.circular(15.0),
                  bottomRight: Radius.circular(15.0),
                ),
                child: Image.network(
                    'https://cdn.pixabay.com/photo/2021/07/12/19/43/swans-6421355_960_720.jpg'),
              ),
            ),
            const SizedBox(
              height: 10,
            ),
            Text(
              'Using Color Constants',
              style: TextStyle(
                fontSize: 28,
                fontFamily: 'Allison',
                color: Colors.blue,
              ),
            ),
            Text(
              'Using Hexadecimal Color',
              style: TextStyle(
                fontSize: 28,
                color: Color(0xFF89B5F7),
              ),
            ),
            Text(
              'Using ARGB Color',
              style: TextStyle(
                fontSize: 28,
                color: Color.fromARGB(255, 255, 128, 200),
              ),
            ),
            Text(
              'Using RGBO Color',
              style: TextStyle(
                fontSize: 28,
                color: Color.fromRGBO(0, 255, 0, 100),
              ),
            )
          ],
        ),
      ),
    );
  }
}

What is the difference between the above code and the home page code?

In this case, we’ve not defined the configuration of the overall visual Theme for a MaterialApp or a widget sub-tree within the app.

We can use the MaterialApp theme to configure the appearance of the entire app. However, in the above case we’ve not followed that principle.

On the contrary, we’ve defined each text style explicitly.

Take one instance and see how it works.

Text(
              'Using Hexadecimal Color',
              style: TextStyle(
                fontSize: 28,
                color: Color(0xFF89B5F7),
              ),
            ),

The above code configures the hexadecimal value. Although as a beginner, we think, using the constant value is better.

Text(
              'Using Color Constants',
              style: TextStyle(
                fontSize: 28,
                fontFamily: 'Allison',
                color: Colors.blue,
              ),
            ),

As a result, we can view the image of the first page, where we have defined text style explicitly.

Material theme flutter changed explicitly
Material theme flutter changed explicitly

If we compare this image with the previous home page image, we’ll understand the difference in color and font style.

Actually when we want to align the appearance of any widget with the overall theme, we must obtain the current theme’s configuration with Theme.of.

It happens because, the Material components typically depend exclusively on the colorScheme and textTheme. These properties are guaranteed to have non-null values.

As a result our null safety principle also keeps intact.

The question is, how does this process work?

When we define theme property in MaterialApp, the static Theme.of method finds the ThemeData value specified for the nearest BuildContext ancestor.

After defining a theme, we can use it into the widget build() methods with the Theme.of(context) method.

Since we’ve defined it earlier, the method looks into the widget tree and returns the very first theme in the tree.

If we have a not defined above our widget, the app’s material theme is returned.

Summing it Up

To sum up, we can say that, certainly we can define theme globally in our MaterialApp widget and all the sub-trees can follow the same material design principles.

However, if we want to change the look for a certain section of our flutter app, we can change the color and font explicitly.

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

GitHub repository

Technical blog

Twitter

Comments

4 responses to “What is a theme in Flutter?”

  1. […] the theming app that we have seen before, we just added an image above the quiz […]

  2. […] the global theme and style consist a color scheme and font that matches the mood of the Flutter Application. We can even use […]

  3. […] captivating tools and fascinating features. As we’ve just reminded, there are Navigator or Theme to help you develop our Flutter […]

Leave a Reply