Material Design: What? Why?
Design Systems are ways of communication, not only between the software and human but also between designers and developers and the other stakeholders. As in software development, we tend to hold to at least one Architectural Pattern so that we communicate better through our code and everyone in the team knows where to write what kind of code and where to look for a specific type of implementation. These standards help in the long run we know that. Similarly, the design system is a way of communicating first, implementation comes second.
We all must speak same the design language, be it a designer, developer or QA or anyone in the process of creation. As Human Interface is for iOS, Atlassian Design System for JIRA, Material Design is for Android.
This design system has First-Class Support for Android. And every design system have some basic guidelines for the core aspects of design
My effort would be to give a very quick walkthrough of what I really want to convey. So let’s get started
There are some finite sets of Named-Colors which if used adequately can do wonders.
The topic of color could easily stretch this article, I would recommend looking here for more on colors. The takeaway is using these terms during conversations and visualizes their effect on our designs and themes.
colorPrimary: The primary branding color for the app.
colorSecondary: The secondary branding color for the app, usually a bright complement to the primary branding color.
colorOn[Primary, Secondary, Surface etc]: A color that contrasts against the named color.
color[Primary, Secondary]Variant: An alternate shade of the given color.
colorSurface: A color for surfaces of components, such as cards, sheets, and menus.
colorBackground: The background for the screen.
colorPrimarySurface: switches between colorPrimary in the Light themes, colorSurface in the Dark theme.
colorError: A color for displaying errors.
What if we need more colors?
Each color added in the system must be purposefully defined. Such a color should be named with a broader scope in mind. For example, color used for Offers and Prizes could also be used to highlight some other information. We should be able to identify nature, where and how can we use this newly introduced color and name it accordingly.
Talking about font family, text sizes, bold | italic | medium, color of text and uncountable combinations of these used together is old school according to Material design guidelines.
The new normal is
The idea is to customize these predefined types as per our needs at a global level of our design system. The later individual component in UI only refers to a type like given below without concerning about how to customize the text.
How are we going to use these types and colors above Globally? It will be covered when we will discuss the theme.
So going forward if we need to emphasise a body text which is set to textAppearenceBody2 a designer would ask to change it to textAppearanceBody1. It will be way more simpler than specifying size 16sp to 14sp and the text color from #2132*** to #232**.
Lets try to understand shapes with a simple Shaadi-like screen given below and then we will define what are shapes and how do they affect our day to day life.
Now lets define shapes quickly:shapeAppearanceSmallComponent is used for Buttons, Chips, Text Fields etc. Defaults to rounded 4dp corners.
shapeAppearanceMediumComponent used for Cards, Dialogs, Date Pickers etc. Defaults to rounded 4dp corners.
shapeAppearanceLargeComponent used for Bottom Sheets etc. Defaults to rounded 0dp corners (i.e. square!)
Well, I could have written about this but it is way better to refer Material Motions page. As it is full of illustrations and animated videos. So lets skip this for a while.
Recap till now.
- Talk about colors and not about its hex-codes
- Talk about types and not about fonts, color, or text-styles. Types are accessible globally as colors are.
- Talk about shape and visualize how changing 1 type of shape will affect other related components.
If we put together all our colors, types and component styles under one name, this is theme. Themes will help us control the look and feel overall by applying set of styles to
- Group of views
- or Individual views.
In short Themes are way of Re-Branding. It is a collection of closely used colors, types, styles, shapes etc. Combination of these will give us uncountable themes. Although we need only handful of themes.
For example lets consider some themes for our App.
- Light theme: Current theme
- Dark Theme: Using muted colors and dark surface
- VIP Theme: If we are planning to create VIP flavor of Android APP
- Rebrand: Some day rebranding will be easier. Let us talk about this a bit.
It would be redundant to say that we are defining new colors, types, shapes etc. Our views are not using actual values of these but the reference from theme. For example a Button originally uses colorPrimary as its base color. And right now it is Sky-Blueish in our App. Later in future if we plan to make it shaadi-red or pink or any other shade of blue then we will still not touch the code of Button. Rather we would update our themes’ colorPrimary and this will be reflected in all the related components in UI automatically.
Now suppose we want to tweak each and every component of our design system, grouping them together will give us a brand new theme.
Also there are various levels of Inheritance and Overriding techniques, using that we could create exceptions for certain views and UI component but that is out of scope of this article.
We are using Material Design Guidelines though we are not sharing it properly. Designer have their own way of doing it and developers have set their own working environment. This has kept us flexible yet with frictions. The color palette is growing, there is no control over types, whereas shapes are yet to be considered as we currently customize at component level.
There is no harm in continuing what we are doing but it does have limitations. Rebranding and experimenting with any component of design system comes with a lot of efforts and will not be confidence inducing for anybody. As we have both relatively new code and some earthy codes. This will increase the efforts of QA and design reviews.
We can do it better only if we do it together. Building up this culture will take some time and efforts, but one day we will be in a state when playing with colors, typography etc across app will be easy-cheesy. We Android-Team had a very healthy discussion regarding this. And we had some approaches that will help us during transitions, with respect to how we are going to define styles? at what level what things will be defined? But this will hold us only until the help arrives. We need more creative people to get involved(Designers| PMs | QA) and standardize everything.
There are certain broad initiatives we could take
- define our colors
- frame our types
- design our shapes
- Put it together; Themes
- Identify Exceptional Themes and Styles
- Use Themes in new screens and layout initially.
- Get them reviewed
- Update older ones and get them reviewed, periodically.
- And Stick to it no matter what.
What a consolidated theme would look like?
<!--Top level DayNight theme to be used in AndroidManifest.xml--> <style name="Theme.MyApp" parent="Base.Theme.MyApp"/> <!--Base custom theme which will be shared between both light and dark theme variants--> <style name="Base.Theme.MyApp" parent="Base.Theme.MaterialThemeBuilder"> <!--Material color attributes (light theme) --> <!--colorPrimary colors map to components and elements, such as app bars and buttons. --> <!--colorSecondary colors are most often used as accents on components, such as FABs and --> <!--selection controls.--> <item name="colorPrimary">@color/purple_500</item> <item name="colorPrimaryVariant">@color/purple_700</item> <item name="colorSecondary">@color/green_200</item> <item name="colorSecondaryVariant">@color/green_500</item> <!--colorBackground appears behind scrollable content and is used for the default window--> <!--background. colorSurface is mapped to the surface of components such as cards, sheets--> <!--and menus. colorError is used to indicate an error state for components such as--> <!--text fields.--> <item name="android:colorBackground">@color/white_50</item> <item name="colorSurface">@color/white_50</item> <item name="colorError">@color/red_600</item> <!--"On" colors define how text, icons and strokes are colored in relation to the surface--> <!--on which they appear.--> <item name="colorOnPrimary">@color/white_50</item> <item name="colorOnSecondary">@color/black_900</item> <item name="colorOnBackground">@color/black_900</item> <item name="colorOnSurface">@color/black_900</item> <item name="colorOnError">@color/white_50</item> <!--Material type attributes--> <item name="textAppearanceHeadline1">@style/TextAppearance.MyTheme.Headline1</item> <item name="textAppearanceHeadline2">@style/TextAppearance.MyTheme.Headline2</item> <item name="textAppearanceHeadline3">@style/TextAppearance.MyTheme.Headline3</item> <item name="textAppearanceHeadline4">@style/TextAppearance.MyTheme.Headline4</item> <item name="textAppearanceHeadline5">@style/TextAppearance.MyTheme.Headline5</item> <item name="textAppearanceHeadline6">@style/TextAppearance.MyTheme.Headline6</item> <item name="textAppearanceSubtitle1">@style/TextAppearance.MyTheme.Subtitle1</item> <item name="textAppearanceSubtitle2">@style/TextAppearance.MyTheme.Subtitle2</item> <item name="textAppearanceBody1">@style/TextAppearance.MyTheme.Body1</item> <item name="textAppearanceBody2">@style/TextAppearance.MyTheme.Body2</item> <item name="textAppearanceButton">@style/TextAppearance.MyTheme.Button</item> <item name="textAppearanceCaption">@style/TextAppearance.MyTheme.Caption</item> <item name="textAppearanceOverline">@style/TextAppearance.MyTheme.Overline</item> <!--Material shape attributes--> <item name="shapeAppearanceSmallComponent">@style/ShapeAppearance.MyTheme.SmallComponent</item> <item name="shapeAppearanceMediumComponent">@style/ShapeAppearance.MyTheme.MediumComponent</item> <item name="shapeAppearanceLargeComponent">@style/ShapeAppearance.MyTheme.LargeComponent</item> <!--Component styles--> <item name="materialAlertDialogTheme">@style/ThemeOverlay.MaterialComponents.Dialog.Alert</item> <item name="bottomSheetDialogTheme">@style/ThemeOverlay.MyTheme.BottomSheetDialog</item> <item name="navigationViewStyle">@style/Widget.MyTheme.NavigationView</item> <item name="toolbarStyle">@style/Widget.MaterialComponents.Toolbar.PrimarySurface</item> </style> <style name="Base.Theme.MaterialThemeBuilder" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <item name="android:statusBarColor" tools:ignore="NewApi">?attr/colorSurface</item> <item name="android:windowLightStatusBar" tools:ignore="NewApi">true</item> <item name="android:navigationBarColor" tools:ignore="NewApi">?android:attr/colorBackground</item> <item name="android:windowLightNavigationBar" tools:ignore="NewApi">true</item> <item name="android:navigationBarDividerColor" tools:ignore="NewApi">?attr/colorControlHighlight</item> </style> </resources>
What shapes would be like?
<!--Shape Appearance for small components like chips, buttons, text fields and FABs--> <style name="ShapeAppearance.MyTheme.SmallComponent" parent="ShapeAppearance.MaterialComponents.SmallComponent"> <!--Your custom shape here--> </style> <!--Shape Appearance for medium components like cards, alert dialogs--> <style name="ShapeAppearance.MyTheme.MediumComponent" parent="ShapeAppearance.MaterialComponents.MediumComponent"> <!--Your custom shape here--> </style> <!--Shape Appearance for large components like side and bottom navigation drawers--> <style name="ShapeAppearance.MyTheme.LargeComponent" parent="ShapeAppearance.MaterialComponents.LargeComponent"> <!--Your custom shape here--> </style>
What types would be like?
<style name="TextAppearance.MyTheme.Headline5" parent="TextAppearance.MaterialComponents.Headline5"> <!--Your custom type style here--> </style> <style name="TextAppearance.MyTheme.Headline6" parent="TextAppearance.MaterialComponents.Headline6"> <!--Your custom type style here--> </style> <style name="TextAppearance.MyTheme.Subtitle1" parent="TextAppearance.MaterialComponents.Subtitle1"> <!--Your custom type style here--> </style> <style name="TextAppearance.MyTheme.Subtitle2" parent="TextAppearance.MaterialComponents.Subtitle2"> <!--Your custom type style here--> </style> <style name="TextAppearance.MyTheme.Body1" parent="TextAppearance.MaterialComponents.Body1"> <!--Your custom type style here--> </style> <style name="TextAppearance.MyTheme.Body2" parent="TextAppearance.MaterialComponents.Body2"> <!--Your custom type style here--> </style>
<!--Color palette--> <color name="purple_200">#bb86fc</color> <!--Color primary (dark)--> <color name="purple_500">#6200ee</color> <!--Color primary (light)--> <color name="purple_600">#4b01d0</color> <!--Color primary variant (dark)--> <color name="purple_700">#3700b3</color> <!--Color primary variant (light)--> <color name="green_200">#03dac6</color> <!--Color secondary--> <color name="green_500">#018786</color> <!--Color secondary variant--> <color name="red_200">#cf6679</color> <!--Color error (dark)--> <color name="red_600">#b00020</color> <!--Color error (light)--> <!--Color surface (light), color on error (light), --> <!--color on surface (dark), color on surface (dark)--> <color name="white_50">#ffffff</color> <color name="black_800">#121212</color> <!--Color surface (dark)--> <!--Color on secondary (light), color on background (light),--> <!--color on surface (light)--> <color name="black_900">#000000</color>