Theming with AppCompat

Ian Lake
Android Developers
Published in
5 min readJan 21, 2016

--

I like standard components — basic building blocks that take care of common functionality and accessibility. I like standard components with a consistent design even better — something that AppCompat provides out of the box. But what I like most of all? Standard components that consistently look awesome and bring personality to my apps. This is what you get when you use the theming provided by AppCompat.

Now you’ll be able to add just a few colors such as colorPrimary, colorPrimaryDark, and colorAccent to your theme and you’ll be able to affect large parts of your app without individually customizing components.

Theming in a material (design) world

When it comes to theming there was a great shift in Lollipop with the introduction of material design. No longer was every button expected to either be exactly the same or completely custom. Tools for generating colorized components or custom colorized action bars went from essential to more than you actually need. Instead, you could customize your theme’s color palette to automatically colorize most of your app. Powerful stuff.

But it shouldn’t be only Lollipop and higher that gets the cool stuff right? So a big focus of AppCompat v21 was in backporting this new theming to all API 7+ devices and support has only grown since then (what with tint-aware widgets being made public in AppCompat 22.1 and even more features added in AppCompat 23.1). This means that a simple theme might look like:

<resources>
<!-- inherit from the AppCompat theme -->
<style name="AppTheme" parent="Theme.AppCompat">
<!-- your app branding color for the app bar -->
<item name="colorPrimary">@color/primary</item>
<!-- darker variant for the status bar and contextual app bars -->
<item name="colorPrimaryDark">@color/primary_dark</item>
<!-- theme UI controls like checkboxes and text fields -->
<item name="colorAccent">@color/accent</item>
</style>
</resources>

Very different from what you might have seen prior to Lollipop (thankfully!).

colorPrimary

The first color you’ll want to add is colorPrimary. This color should represent your primary branding color which users should associate with your app (hence its ‘primary’ name). And obviously the first thing to be colored with colorPrimary should be your app bar.

When using a base theme of Theme.AppCompat and the AppCompat-provided app bar, you’ll find the app bar’s background automatically uses your colorPrimary. However, if you’re using a Toolbar (along with a Theme.AppCompat.NoActionBar theme, most likely), you’ll need to manually set the background color.

<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary" />

As mentioned in our previous pro-tip on colorizing the App Bar, the ?attr/ format is how you tell Android that this value should be resolved from your theme rather than directly from a resource. Generally when choosing a colorPrimary, consider colors from the material color palette around the 500 value.

colorPrimaryDark

As you might expect from the name, colorPrimaryDark is a darker variant of your primary color, which is used as the background color of the status bar that adorns the top of the screen. This difference in color gives users a clear separation between the system-controlled status bar and your app. Compared to colorPrimary, this should be the 700 color from the color palette of the same shade.

While AppCompat can backport a lot of things, coloring the status bar correctly relies on new APIs introduced in Lollipop (namely windowDrawsSystemBarBackgrounds), so don’t expect to see a colorPrimaryDark status bar on older platform versions.

colorAccent

Where colorPrimary and colorPrimaryDark are more suitable as a background color for sections of your UI, the vast majority of times you’ll see colorAccent is in small quantities that provide a contrasting color to draw attention to certain components.

In fact, many of the built in components already use colorAccent:

While you may notice quite a few more apps focusing on colorPrimary and colorPrimaryDark (they are primary after all), colorAccent can be an easy way to guide user’s attention, provide context, and inspire confidence (all important things if you look at user research!).

More colors

If those three main colors aren’t quite enough, you don’t have to resort to coloring specific components quite yet: there are a few more colors in the color palette which can help fine tune certain things for you:

  • colorControlNormal controls the ‘normal’ state of components such as an unselected EditText, and unselected Checkboxes and RadioButtons
  • colorControlActivated overrides colorAccent as the activated or checked state for Checkboxes and RadioButtons
  • colorControlHighlight controls the ripple coloring

Theming Views with the help of Theme Overlays

The example theme above had a parent theme of Theme.AppCompat. If you’ve ever looked at the base theme’s source code, you’ll see that the theme sets just about everything possible, as you’d expect for an Activity’s theme. However, Lollipop and AppCompat as of version 22.1 make it possible to apply themes to individual Views.

As mentioned in our previous pro-tip, a ThemeOverlay is a separate type of parent theme that only changes what is needed — for example, ThemeOverlay.AppCompat.Light changes background colors, text colors, and highlight colors as if it was a light theme and ThemeOverlay.AppCompat.Dark does the same for switching to a dark theme.

This is particularly prevalent when it comes to the Toolbar, so much so that there are separate ThemeOverlay.AppCompat.ActionBar and ThemeOverlay.AppCompat.Dark.ActionBar, which also change colorControlNormal to android:textColorPrimary and set the correct SearchView styling as is expected for those components:

<!-- Ensure text is readable on a dark background by using a 
Dark ThemeOverlay -->
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

Of course, the real power here is in building your own custom ThemeOverlay, which is done like any other theme — just make sure you are using a variant of ThemeOverlay.AppCompat as the parent theme:

<style name="ThemeOverlay.AccentSecondary"
parent="ThemeOverlay.AppCompat">
<item name=”colorAccent”>@color/accent_secondary</item>
</style>

As it is those ThemeOverlay.AppCompat parent themes that automatically translate the AppCompat colorPrimary into the Lollipop+ framework android:colorPrimary attributes — you’ll find things aren’t quite what you expect if you leave out the parent theme!

Themes: useful for every app

So whether you have a design team, a single designer, or are working through the design of your app yourself, using the theming colors available to you is an important first step and ensures you get the most out of the standard components without resorting to an app of mostly different shades of gray.

#BuildBetterApps

Join the discussion on the Google+ post and follow the Android Development Patterns Collection for more!

--

--