Flutter

Flutter Button Theme

By January 8, 2020 January 1st, 2021 No Comments

When I started developing in Flutter, I first had many doubts on how to use the buttons, how to customize them and I got puzzled on how to theme them!
So I had dug a bit and summarized the type of Buttons in this guide of flutter buttons.
In this post, I will try to provide all the necessary information to answer some questions.
What type of Flutter Button should I use? How can I customize my button? A FlatButton with elevations is the same as the RaisedButton?

First of all. Let me point out what are the differences among the common Flutter buttons and how they are related.

MaterialButton

  • It provides a default padding.
  • It is disabled if onPressed parmeter is null. Automatically colored as grey.

FlatButton       

It is a MaterialButton, basically there is no difference. But for clarity it is recommended to use FlatButton class.

RaisedButton

It is a MaterialButton with shadow/elevetation when pressed and colored background or gray if disabled.

OutlineButton

Same as FlatButton with a border grey line as shape by default.

To change the border color when pressed, use property highlightBorderColor.

To change the border color  when is not pressed, you need to customize borderSide with BorderSide(color:Color.xxx)

Buttons with Icon

To add an icon we can use FlatButton.icon, RaisedButton.icon, OutlineButton.icon.

IconButton

It is just an Icon (no text). This Button is typically used on the AppBar.

Customize Buttons

For all the Buttons above you can customize the appearance individually using the following properties:

color: Background color for a Button. It will override any themed color provided.

FlatButton(color:Colors.cyan,child: Text("FlatButton"),onPressed: ()=>{},),

shape: It provides a shape of the button.

Another example:

     FlatButton(
              color:Colors.cyan,
              shape: ContinuousRectangleBorder(
              side: BorderSide(color:Colors.cyan[900],width: 4),
                  borderRadius: BorderRadius.circular(80.0)),
              child: Text("FlatButton"),onPressed: ()=>{},),

Theming Buttons

There are two classes that provide theming to buttons into our App. ThemeData and ButtonThemeData.
We can customize (coloring but no shape) Buttons using the following attributes in ThemeData.

  • ThemeData.buttonColor: Default background color used by RaisedButtons. If not provided, the primarySwatch[600] is used (in some cases, see below).

💡 If you want to fill with color a FlatButton or OutlineButton then use parameter color when building the button.

  • ThemeData.splashColor: Color to start filling the Buttons when pressed. (The ripple color in Android).
  • ThemeData.highlightColor: Color used to fill the background when splash has ended.
  • ThemeData.hoverColor: Color when the mouse passes over it. (Not visible on mobile native).

❗ ThemeData.brightness is important. It might change the color of the button. See examples in section Theme Buttons Table

ButtonThemeData

But wait! if you define a ButtonThemeData, all properties above can be overridden by ButtonThemeData.

It let us define some  attributes, like:

  • ButtonThemeData.buttonColor: Same as ThemeData.
  • ButtonThemeData.splashColor: Same as ThemeData used in FlatButton, OutlineButton or RaisedButton.
  • ButtonThemeData.highlightColor: Same as ThemeData.
  • ButtonThemeData.hoverColor: Same as ThemeData.
  • ButtonThemeData.minWidth: Default minimum width.
  • ButtonThemeData.height: Default height.
  • ButtonThemeData. padding: Default padding.
  • ButtonThemeData.shape: Default shape.

Particularities using ThemeData and ButtonThemeData

It could not be that easy!

I found some issues on theming the buttons when trying some Google CodeLabs or creating my Apps… And this is why:

 

⚠️ If ButtonThemeData is provided, values from ThemeData won’t be taken into account at all!

 

⚠️So some things we need to keep in mind:

  •  buttonColor, splashColor,hoverColor,highlightColor from ThemeData will be used to build a ButtonThemeData internally (if none is provided)  when calling constructor ThemeData().
  • if you try to use ThemData.copyWith(buttonColor:..) the ButtonThemeData won’t be recreated using the buttonColor and you won’t have the desired result.
  • buttonColor. The color used for background color in RaisedButton. If no defined , the theme color primarySwatch is used (If theme is light, grey if it is dark). Check the method ButtonThemeData.getFillColor to know how it is filled.
  • For splashColor. ⚠️ Flat, Raised or OutlineButton define splashColor in ButtonThemeData.

For instance, observe the result if we have defined this ButtonThemeData in the Theming without providing a  splashColor:

theme: ThemeData(
       primarySwatch: Colors.green,
       splashColor: Colors.pink,
       buttonTheme: ButtonThemeData(
        // splashColor:Colors.pink,   //we don't define the splashColor in ButtonThemeDaa
        height:60
      )
   ),

The result:

Theming Buttons

You can customize all InkWell, Icon or MaterialButton in the App defining attributes in the ThemeData.

Watch out the ButtonBar

Let’s see what happens to wrap a RaisedButon and a FlatButton in the ButtonBar.

Umh 🤔. Why FlatButton in a ButtonBar uses another color? Yeah.. this is how is made ButtonBar. As we can read in the doc:

The children are wrapped in a ButtonTheme that is a copy of the surrounding ButtonTheme with the button properties overridden by the properties of the ButtonBar as described above.

This is giving us a clue about what is going on here. Fortunately, we can inspect all Flutter widgets since they are implemented in Dart.

Checking the code of ButtonBar, we spot that indeed the ButtonBar wraps the buttons in a new ButtonTheme copied from the one from the ThemeData (either built internally or the one provided by us). But it will override the ButtonTextTheme to use the ButtonTextTheme.primary, while the default value is ButtonTextTheme.normal.

So that is why the FlatButton shows in blue (in this example I have not provided a primarySwatch, so the default one is Colors.blue  for a Theme).

Is this the desired behavior? Maybe… But it is confusing since it is also not consistent with Material.io Buttons

Theme Button Table

Here you can find some examples of different Theme setups and their results.

 

ThemeData(
primarySwatch: Colors.red,

 

ThemeData(
primarySwatch: Colors.red,
buttonTheme: ButtonThemeData()

 

ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.red,
buttonTheme: ButtonThemeData()
//Empty ButtonThemeData
//has no effect on dark Themes

 

ThemeData(
primarySwatch: Colors.red,
buttonColor: Colors.red,

 

ThemeData(
buttonColor: Colors.red,

 

ThemeData(
primarySwatch: Colors.red,
splashColor:Colors.pink
buttonTheme: ButtonThemeData()

 

ThemeData(
primarySwatch: Colors.red,
splashColor:Colors.pink
buttonTheme: ButtonThemeData(
splashColor:Colors.pink
)

 

Conclusion

Defining the primarySwatch in ThemeData is important to avoid undesired colors to appear.

Define buttonColor,splashColor,etc in ThemeData is not enough. It is usually needed to be defined as well in ButtonThemeData. Ideally in both.

Keep in mind ThemeData creates a ButtonThemeData internally with predefined values (explained above). So take this into account if you use ThemeData.copyWith() or similar.

Once again, as it happened on themes in Android. Theming buttons in Flutter is becoming a bit confusing.

I created this article because I had many doubts about what characteristics had each Button and I was not sure when/what/how to customize or theme.

Hope this little article helps you to use the Flutter Buttons in a better way.

If you find any error or you have suggestions, please let me know! I will be happy to learn and to correct any possible mistakes.

 

Happy Fluttering!

Ernie

Author Ernie

More posts by Ernie

Leave a Reply