How to Define Flutter Theme
Tags: flutter, android, theme, beginners
Published: 2022-04-22 00:26:23

In this short blog series, we will define a global theme for our applications.  We'll mainly work on two aspects colors and fonts. Check out the style guide below.
![Figma Style Guide](https://cdn.hashnode.com/res/hashnode/image/upload/v1648449659216/aX4MY1bZa.png)

## Intro 
Welcome back to 3<sup>rd</sup>  part of the series "__Flutter App Development Tutorial__". So, far we implemented [Launch Icon, Splash Screen](https://dev.to/kcl/create-splash-screen-and-launch-icon-in-flutter-1kdg) and [Onboard Screen](https://dev.to/kcl/onboarding-with-go-router-in-flutter-2jd6).  Please find the source code for the progress so far from [here](https://github.com/nibukdk/astha-tutorial/tree/master/part_two).

Now, since this application is for Hindus, I tried to apply a few holy colors like Saffron as the primary color, red as an accent/secondary color, and Green as the background color of the app. The text colors are the result of experimenting with color contrast. For the font, I am using Proxima Nova. You can download your fonts from [here](https://fontsfree.net/proxima-nova-rg-regular-font-download.html?preview=Lorem+ipsum+dolor+sit+amet%2C+consectetur+adipiscing+elit.+Eu+id+lectus+in+gravida+mauris%2C+nascetur.+Cras+ut+commodo+consequat+leo%2C+aliquet+a+ipsum+nulla.).

## Styling Your Flutter App
Alright, now that we've seen what our app's roughly going to look like. Let's create a __theme__ folder and a file __app_theme.dart__ inside the globals folder.


```
#on the root of project
mkdir lib/globals/theme

# Create file
touch lib/globals/theme/app_theme.dart

``` 
### Defining Themes With ColorScheme

Now inside the __app_theme__ file let's define the colors that our app is going to use. 

__app_theme.dart__

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

// Instantiate new  theme data
final ThemeData asthaTutorialTheme = _asthaTutorialTheme();

//Define Base theme for app
ThemeData _asthaTutorialTheme() {
// We'll just overwrite whatever's already there using ThemeData.light()
  final ThemeData base = ThemeData.light();

  // Make changes to light() theme
  return base.copyWith(
    colorScheme: base.colorScheme.copyWith(
 
      primary: const Color.fromARGB(255, 255, 153, 51),
      onPrimary: Colors.white,
      secondary: const Color.fromARGB(255, 223, 27, 12),
      onSecondary: Colors.white,
      background: const Color.fromARGB(255, 228, 243, 228),
      onBackground: Colors.black,
    ),
  );
}

```
Flutter [ColorScheme](https://api.flutter.dev/flutter/material/ColorScheme-class.html) can be used to define the colors of many components. Copying the [Light](https://api.flutter.dev/flutter/material/ColorScheme/ColorScheme.light.html) theme leaves us less work to do. However, if you've tried the [dark](https://api.flutter.dev/flutter/material/ColorScheme/ColorScheme.dark.html) theme you're gonna need to experiment a little bit, cause some colors might get overwritten. The primary color is for navigation/app bars while the secondary is the accent color. We must define styles for buttons separately with respective [ButtonTheme](https://api.flutter.dev/flutter/material/ButtonTheme-class.html) class. 

### Defining Text Theme 
As mentioned before we'll be using [ProximaNova](https://fontsfree.net/proxima-nova-rg-regular-font-download.html?preview=Lorem+ipsum+dolor+sit+amet%2C+consectetur+adipiscing+elit.+Eu+id+lectus+in+gravida+mauris%2C+nascetur.+Cras+ut+commodo+consequat+leo%2C+aliquet+a+ipsum+nulla.) font. Create __fonts__ folder inside assets folder and download the font if you'll be using the same one. Now, as we've done previously we need to tell flutter to look for the font by adding path on the pubspec file. 

The fonts section should be commented on in the pubspec file, uncomment it if you want, add the following instructions.
```
 fonts:
    - family: Proxima Nova Rg Regular
      fonts: 
        - asset: assets/fonts/ProximaNovaRegular.ttf

``` 

Let's now head back to our theme and begin writing instructions for what our texts are gonna look like. We'll create a separate function **_asthaTutorialTextTheme** to keep our main function lean.
 

```
 // Outside of _asthaTutorialTheme function  create another function

TextTheme _asthaTutorialTextTheme(TextTheme base) => base.copyWith(
// This'll be our appbars title
      headline1: base.headline1!.copyWith(
          fontFamily: "Proxima Nova Rg Regular",
          fontSize: 30,
          fontWeight: FontWeight.w500,
          color: Colors.white),
// for widgets heading/title
      headline2: base.headline2!.copyWith(
        fontFamily: "Proxima Nova Rg Regular",
        fontSize: 26,
        fontWeight: FontWeight.w400,
        color: Colors.black,  
      ),
// for sub-widgets heading/title
      headline3: base.headline3!.copyWith(
        fontFamily: "Proxima Nova Rg Regular",
        fontSize: 24,
        fontWeight: FontWeight.w400,
        color: Colors.black,
      ),
// for widgets contents/paragraph
      bodyText1: base.bodyText1!.copyWith(
          fontFamily: "Proxima Nova Rg Regular",
          fontSize: 20,
          fontWeight: FontWeight.w300,
          color: Colors.black),
// for sub-widgets contents/paragraph
      bodyText2: base.bodyText2!.copyWith(
          fontFamily: "Proxima Nova Rg Regular",
          fontSize: 18,
          fontWeight: FontWeight.w300,
          color: Colors.black),
    );

``` 
In flutter, [TextTheme](https://api.flutter.dev/flutter/material/TextTheme-class.html) is a material design class for text . I've tried to provide font size and font weight to maintain a hierarchy and be less bland.  

After defining the function, we'll need to pass it to our main function: _asthaTutorialTheme.


```

// Inside the base.copyWith method 
....
  return base.copyWith(
    colorScheme: base.colorScheme.copyWith(
   // Leave it as it is
      ....    ),
    // Add text theme
    textTheme: _asthaTutorialTextTheme(base.textTheme),
  );

``` 


### Elevated Button Theme in Flutter

[ElevatedButtonThemeData](https://api.flutter.dev/flutter/material/ElevatedButtonThemeData-class.html)  is a button style that overrides the default appearances of ElevatedButtons. Like previously, we'll create a separate function to define the button style.

```
ElevatedButtonThemeData _elevatedButtonTheme(ElevatedButtonThemeData base) =>
    ElevatedButtonThemeData(
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all<Color>(
          const Color.fromARGB(255, 223, 27, 12),
        ),
        foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
      ),
    );

``` 
[Material StateProperty](https://api.flutter.dev/flutter/material/MaterialStateProperty-class.html) contains the state of a widget's material. Button like elevated, text or outline is consists of many material state properties such as background color, that's why we're defining color property like in our code above.
With that out of the way, let's pass this function to the *elevatedButtonTheme* property inside a copy of the base theme.


```
    // below text theme add this
    // Define styles for elevated button
    elevatedButtonTheme: _elevatedButtonTheme(base.elevatedButtonTheme),

``` 
### Styling Input Widgets in Flutter

We're going to be using input forms for authentication later on in the series. We'll need to add a few styles for that as well.


```
InputDecorationTheme _inputDecorationTheme(InputDecorationTheme base) =>
    const InputDecorationTheme(
// Label color for the input widget 
      labelStyle: TextStyle(color: Colors.black),
// Define border of input form while focused on 
      focusedBorder: OutlineInputBorder(
        borderSide: BorderSide(
          width: 1.0,
          color: Colors.black,
          style: BorderStyle.solid,
        ),
      ),
    );

``` 
We've made input such that when focused on it'll have a solid border with a width of 1px. Similarly, colors for both text and border will be black.

Can you add the **_inputDecorationTheme** function to our main function? I'll leave it to you then.

Now, putting it all together:

__app_theme.dart__


```
import 'package:flutter/material.dart';
// Kinda like a getter to import theme from other files
final ThemeData asthaTutorialTheme = _asthaTutorialTheme();

//Define Base theme for app
ThemeData _asthaTutorialTheme() {
  final ThemeData base = ThemeData.light();

  return base.copyWith(
    colorScheme: base.colorScheme.copyWith(
      primary: const Color.fromARGB(255, 255, 153, 51),
      onPrimary: Colors.white,
      secondary: const Color.fromARGB(255, 223, 27, 12),
      onSecondary: Colors.white,
      error: Colors.red,
      background: const Color.fromARGB(255, 228, 243, 228),
      onBackground: Colors.black,
    ),
    textTheme: _asthaTutorialTextTheme(base.textTheme),
    // below text theme add this
    // Define styles for elevated button
    elevatedButtonTheme: _elevatedButtonTheme(base.elevatedButtonTheme),

    // Set Themes for Input Your homework
    
    // Define theme for text input
   
  );
}

// Outside of _asthaTutorialTheme function  create another function

TextTheme _asthaTutorialTextTheme(TextTheme base) => base.copyWith(
// This'll be our appbars title
      headline1: base.headline1!.copyWith(
          fontFamily: "Proxima Nova Rg Regular",
          fontSize: 30,
          fontWeight: FontWeight.w500,
          color: Colors.white),
// for widgets heading/title
      headline2: base.headline2!.copyWith(
        fontFamily: "Proxima Nova Rg Regular",
        fontSize: 26,
        fontWeight: FontWeight.w400,
        color: Colors.black,
      ),
// for sub-widgets heading/title
      headline3: base.headline3!.copyWith(
        fontFamily: "Proxima Nova Rg Regular",
        fontSize: 24,
        fontWeight: FontWeight.w400,
        color: Colors.black,
      ),
// for widgets contents/paragraph
      bodyText1: base.bodyText1!.copyWith(
          fontFamily: "Proxima Nova Rg Regular",
          fontSize: 20,
          fontWeight: FontWeight.w300,
          color: Colors.black),
// for sub-widgets contents/paragraph
      bodyText2: base.bodyText2!.copyWith(
          fontFamily: "Proxima Nova Rg Regular",
          fontSize: 18,
          fontWeight: FontWeight.w300,
          color: Colors.black),
    );

InputDecorationTheme _inputDecorationTheme(InputDecorationTheme base) =>
    const InputDecorationTheme(
// Label color for the input widget
      labelStyle: TextStyle(color: Colors.black),
// Define border of input form while focused on
      focusedBorder: OutlineInputBorder(
        borderSide: BorderSide(
          width: 1.0,
          color: Colors.black,
          style: BorderStyle.solid,
        ),
      ),
    );

ElevatedButtonThemeData _elevatedButtonTheme(ElevatedButtonThemeData base) =>
    ElevatedButtonThemeData(
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all<Color>(
          const Color.fromARGB(255, 223, 27, 12),
        ),
        foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
      ),
    );

``` 
### Adding Theme to GoRouter 

We're using [MaterialApp.router](https://api.flutter.dev/flutter/material/MaterialApp/MaterialApp.router.html) class for declarative routing. It provides a field __theme__ to definine global theme for its children. So, in out __app.dart__ file where we call upon this class, let's add the theme we just defined.

__app.dart__


```
// import theme at top
import 'package:temple/globals/theme/app_theme.dart';

//In MaterialApp.router
          return MaterialApp.router(
              routeInformationParser: router.routeInformationParser,
              theme: asthaTutorialTheme, // add our theme here.
              routerDelegate: router.routerDelegate);

``` 

* A kind reminder, your package name can be different while importing* 

### Test  Theme  

I've changed the __Home__ screen a little bit, to test our theme. Please feel free to experiment on your own.

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

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

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: Icon(Icons.person),
        title: Text(
          "This is appbar",
          style: Theme.of(context).textTheme.headline1,
        ),
      ),
      body: SafeArea(
        child: Container(
            padding: const EdgeInsets.all(20),
            color: Theme.of(context).colorScheme.background,
            child:
                Column(mainAxisAlignment: MainAxisAlignment.start, children: [
              Card(
                child: Container(
                  width: 300,
                  height: 200,
                  padding: const EdgeInsets.all(4),
                  child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          "Hi",
                          style: Theme.of(context).textTheme.headline2,
                          textAlign: TextAlign.left,
                        ),
                        Text(
                          "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Eu id lectus in gravida mauris, nascetur. Cras ut commodo consequat leo, aliquet a ipsum nulla.",
                          style: Theme.of(context).textTheme.bodyText1,
                        )
                      ]),
                ),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  TextButton(
                    child: const Text("Text Button"),
                    onPressed: () {},
                  ),
                  ElevatedButton(
                    child: Text(
                      "Hi",
                      style: Theme.of(context).textTheme.bodyText1!.copyWith(
                            color: Colors.white,
                          ),
                    ),
                    onPressed: () {},
                  ),
                ],
              )
            ])
           ),
      ),
    );
  }
}

``` 

The code yielded the following screen.

![Homepage for Theme Practice](https://cdn.hashnode.com/res/hashnode/image/upload/v1648460047958/S7-DBVe_c.png)

## Homework
Do me a favor I've forgotten to add the text theme in the code, can you add it by yourself?



![KCl](https://cdn.hashnode.com/res/hashnode/image/upload/v1649239187724/R8tqX5bq0.png)

## Summary
In this blog series:
1. We defined a set of colors for our app.
2. We also added font and then defined styles for texts. 
3. We gave a border to the input form that our app will use. 
4. Then we also tested the theme with a mock page.


If you want to learn more, visit Google Shrine App Tutorial, [MDC-103](https://codelabs.developers.google.com/codelabs/mdc-103-flutter#0).

## Support Us

Many things are yet to be done like Authentication Using Firebase, Firebase Firestore, and Functions. Find the list of all the blogs in this series [here](https://dev.to/kcl/series/17729).

I hope this blog was worth your time. If you have any queries let us know in the comment section. Don't forget to like and share them with your friends. Please do __subscribe__ to get email updates.

This is Nibesh Khadka from Khadka's Coding Lounge, a freelancing agency. We make high-value mobile apps and websites at a reasonable price. 

![Like, Comment, and Subscribe](https://cdn.hashnode.com/res/hashnode/image/upload/v1648460364676/r5bN5DQIB.png)