From AppCompat to Material Components + Applying Dark theme to Android (Part 1/4)

Shubham Gupta
6 min readApr 11, 2020

The Material Design library came with a big update which includes new UI elements(components), guidelines and a lot more. Today, I will show you how you can follow the newest Material Design update into your current apps and add support for a dark theme as well.

Before we learn how to implement a dark theme in our apps, we need to understand why there is a need to use new material design components.

Why a new Material Design library?

Well, the original Material Design was good enough to create beautiful apps/websites. But it was not enough to create a brand that could stand out of the crowd. For eg- If we compare the old Gmail and Microsoft’s Outlook email app which follows the Material Design guidelines, they will look nearly the same. Mostly, the changes will be in brand color or fonts. But it will still look similar to other email apps. Thus, Google created a new library to let brands express their own identity.

What are the changes in the new Material Design library?

The new Material Design library is built on the top of the original Material Design Support library i.e. they are based on the original concept of paper and ink that represents the real world. Thus material can have motion or change its shape according to its surroundings. The new changes include:

  1. Color
  2. Typography
  3. Shape

To implement the above changes, we need to follow Material theming. Material theming is an ability to customize Material Design so that our brand looks unique. It provides a way to easily customize any future changes. As a developer, we would like to change the things at once place and see it changed at every other place. Material theming is a way of achieving this.

Steps on how to apply dark theme into your apps:

  1. Use material theming i.e. use color, typography, shape design systems. This will be covered in Part 1, Part2, and Part 3.
  2. Extend material theming to add dark theme support. This will be covered in Part4.
  3. (Optional) Give a user the option to change the theme(light/dark). This too will be covered in Part4.

I will try to give the best guidelines while implementing dark themes.

Implementing Material Theming(Convert AppCompat to MaterialComponents)

Till now our apps were using AppCompat themes and colors such as colorPrimary, colorPrimaryDark and colorAccent. To follow the new color system either you can continue with some of them or change to the new colors. The new color system is:

Color chart showing 12 categories of colors (credits: Google)

You can read about these new colors here. The above colors are provided by default. You just need to change the ones you want to express your brand. In my experience, the easiest way is to use the default colors and then gradually start to change the primary and secondary colors.

If you continue with the old colors, the android framework will convert them automatically to use the new color category. The conversion works as follows:

New vs old color theme attributes (credits: Google)

For eg: If you are using colorAccent, then the system will consider it as colorSecondary color and apply it wherever the secondary color is applicable(FAB, switches, Progress Bars, etc). But I will suggest you to completely use the new colors to prevent any future color compatibility issues.

Looking at the above comparison, see that the colorControl*, colorButtonNormal, etc. are taken care of by the system. Therefore you don’t need to explicitly specify them.

Steps to move to the new material theming:

1. Change the parent theme to use the Material Component theme

Add the following dependency(check the latest version here) and make sure you have migrated to AndroidX libraries and compileSdkVerison is at least 28(Android 9). Moreover, your activities should extend from AppCompatActivity or AppCompatDelegate.

implementation "com.google.android.material:material:1.2.0-alpha05"

In themes.xml, change the parent theme to:

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">

2. Create a new themes.xml file i.e res/values/themes.xml

You should move the code which specifies the app theme(and Theme Overlays) from styles.xml to themes.xml. We are doing this because themes and styles are different. Theme attributes are applied to our whole app while styles are applied to the views. For eg: colorPrimary is a theme attribute. You cannot apply this to a view attribute i.e. android:colorPrimary="@color/red” would be wrong. To learn more about styles vs themes, check this fantastic article by Nick Butcher. Continue to keep the Widget(Buttons/Text) styles in styles.xml as before. This enables the separation of concerns.

3. Change the colors to use the new color system

Replace the colorPrimaryDark with colorPrimaryVariant and colorAccent with colorSecondary. Provide a specific status bar color. After changes your code should look something like this:

Moved from styles.xml to themes.xml. If you are starting a new project, styles.xml will be empty right now.

You can see that we have added the DayNight qualifier which means that we have taken the first step to add a dark theme as well. If you run the app now and switch to dark mode, you will see some changes in the app. We’ll see in Part 4 on how to customize our app for the dark theme as well.

To generate a new color palette or play with colors, check this or this.

4. Give literal naming to colors(Optional but recommended)

While semantically naming the color resources(as colorPrimaryDark or colorPrimary) works, it’s better to provide a literal name to the color. It can be the name of the color for eg: red, green, blue with various versions like dark red, light red or sky blue. Or it can be named on material colors like material_blue_500 or material_pink_a200.

Tip: While referring to color resources in layouts, don’t use a reference to the colors directly. Instead, use theme attributes. That means, instead of referring android:textColor=”@color/red", use android:textColor="?attr/colorPrimary". This will maintain consistency across your app. To read more, check this.

What if we have to use more colors than our color palette?

For eg: You may have to implement a divider which takes a grey color. But your color palette does not have grey color. To prevent adding grey color you can use black color with an alpha value applied to it. This will work nicely in both light and dark themes. For eg:

We are using a color state list which can be beneficial to prevent multiple variants of a single color. Thus if our colorOnBackground changes we do not need to change this file at all.

While useful, there are some gotcha’s to be aware of.

1. If the specified color also has an alpha value, then the alphas are combined e.g. applying 50% alpha to 50% opaque white would yield 25% white. For this reason, it’s preferable to specify theme colors as fully opaque and use ColorStateLists to modify their alphas.

2. The alpha component was only added in API 23 so if your min SDK is lower than this, be sure to use AppCompatResources.getColorStateList which backports this behavior (and always use the namespace, never the namespace).

3. Often we use a shorthand to set a color as a drawable e.g.

<View android:background=”@color/fooBar”/>

A View’s background is a drawable, this shorthand coerces the given color to a ColorDrawable. However, there is no way to convert a ColorStateList to a Drawable (before API 29 when ColorStateListDrawable was introduced to solve this issue). We can, however, work around this restriction:

<View
android:background=”@drawable/a_solid_rectangle_shape_drawable”
app:backgroundTint=”@color/a_color_state_list”/>

Be sure that your background tint supports the states your view needs e.g. if it needs to change when disabled.

Your app has taken the first step to build a beautiful and easy to customizable design. Check the next part to learn about applying consistent typography into your theme.

For any suggestions/mistakes, don’t hesitate to add a comment. :)

References

  1. www.material.io
  2. Build your material theme
  3. https://youtu.be/IaT4wdWTwuo
  4. https://github.com/material-components/material-components-android/blob/master/docs/getting-started.md

--

--

Shubham Gupta

Programming Enthusiast, Google Certified Android Developer, Sarcasm and Humour lover, Being a better me.