Flutter design: make your theme homogeneous
Tuesday 06 July 2021 09:06 AM Beirut Time · 833
Wajdi Alkayal Wajdi Alkayal
Flutter design: make your theme homogeneous

Flutter design: make your theme homogeneous

In a lot of Flutter source codes and applications, I observed a recurring practice consisting in adding custom style directly through widget parameters, leading to an inconsistent design and extra maintenance. As a personal example, I have to maintain a Flutter application where all titles had different font size (and sometime font weight).

In this article, I will explain you the importance of the way you should design your Flutter application, especially focusing on the theme.

In your opinion, what is the difference between these ‘settings’ pages in term of code ?
What is the right way to apply a theme to your application ?
In the image above, ‘settings’ pages share the exact same code. There is strictly no difference between those four designs at this level.

There is nothing magic underneath: all theming related stuff have been centralized at higher level, in the MaterialApp widget. This widget allow you to define two themes, one for light brightness, the other for a dark theme mode.

Added to that, most of widgets are retrieving their design from it, if no value is given.

Let’s take an example on how to do this properly: the Card widget. You can observe that in the third example of settings page, the shape has ‘straight lines’ instead of corners.
/// The shape of the card's [Material].
///
/// Defines the card's [Material.shape].
///
/// If this property is null then [CardTheme.shape] of [ThemeData.cardTheme]
/// is used. If that's null then the shape will be a [RoundedRectangleBorder]
/// with a circular corner radius of 4.0.
final ShapeBorder? shape;
ThemeData example() {
final base = ThemeData.dark();
final mainColor = Colors.lightBlue;
return base.copyWith(
cardColor: Color.lerp(mainColor, Colors.white, 0.2),
cardTheme: base.cardTheme?.copyWith(
color: Color.lerp(mainColor, Colors.black, 0.1),
margin: EdgeInsets.all(20.0),
elevation: 0.0,
shape: BeveledRectangleBorder(
borderRadius: BorderRadius.circular(14.0),
side: BorderSide(color: Colors.white24, width: 1)),
),
);
}
The above code illustrate how to change the card design, but you can do it for pretty much every widgets coming from Flutter SDK. Also, you should centralize theme related stuff into a single file, because ThemeData is a huge data structure.
ThemeData covers every widgets, right ?

Unfortunately, ThemeData does not cover all widgets. For example, you cannot define list tiles design in there. Fortunately, you can achieve this through the ListTileTheme widget.
That how we can change list tile selected color and padding, without explicitly set it in the source code of the page.
ListView.builder(
itemBuilder: (context, index) {
final value = elements[index];
return ListTile(
selected: value == selected,
title: Text(value.title),
subtitle: Text(value.message),
leading: Icon(value.icon),
onTap: () => setState(() => selected = value),
);
},
itemCount: elements.length,
);

As you can see in the code, there is nothing related to the design. It as the advantage to avoid code noises, making it succinct and easier to understand. Also, one thing I like is in the fact that all my methods are small (less than 30 lines).

Conclusion

In this article, we saw how to centralize the application design into the ThemeData object. As you may understood, you may have to read a lot of the Flutter SDK code documentation for that purpose, but benefits will come when you or another colleague will have to maintain it:

Avoid code duplication

Less code in your pages, making code easier to be read and understood

Ensure design consistency

But as you may have seen, the ThemeData object is a really big structure, in constant evolution. So keep an eye on it !

To go further more…

Two more little tips for you! First, if you want to have a specific design for one of your component, instead of customizing it inside the build method, you can wrap your widget into the Theme widget.

When you design a new widget, you may want to imitate the SDK widgets, by retrieving theme information from the ThemeData. You may have seen that inheritate from ThemeData is not the right way. Instead, you can “extends” it through InheritedTheme widget, and imitate how it’s implemented like in ListTileTheme widget.

Related Posts
Graphic design
09 June
The Power of Email Marketing
03 June
Photography
01 June