How to make Android Toolbar follow Material Design guidelines

Update: February 2017

Lucas Urbas
5 min readJan 25, 2015

--

Two years after writing this article the Toolbar from support library still is not perfect. Sdk version 24 introduced a small improvement with methods setContentInsetWithNavigation(int) and xml attr app:contentInsetStartWithNavigation with default Title offset set to 72dp. The major part of this article is still valid. Recently I’ve updated the project on Github to use latest libraries and also made a small android from it available as maven dependency. You can use everything described in this blog post with simple:

dependencies {
compile 'com.lucasurbas:guidelinescompattoolbar:1.0.0'
}

Just make your application theme extends one of Theme.GuidelinesCompat. You can find more in readme file. Now, lets get back to the show…

Toolbar

The toolbar is a great concept. Unplugging action bar from decor view, making it a standalone view suddenly gave us so much space for customization and creation. But with this amount of freedom also come the extra amount of work. Lots of people don’t even realize, that Toolbar doesn’t follow few basic material design guidelines. I don’t know if it’s a bug or a conscious decision. It’s possible, that in next release of AppCompat library all things I’m going to talk about will be deprecated. But if it happens, I will be very happy to see it.

So what am I talking about anyway? I’ve been studying guidelines for a while and found few glitches in official implementation.

This is how it should look like:

Source: http://www.google.com/design/spec/layout/structure.html#structure-app-bar

And this is how it was created:

Finding the difference

In the specification, navigation and action buttons have the same size. Icons have both width and height of 24dp. Minimum size of a touchable element shouldn’t be smaller than 48dp, so buttons have additional 12dp padding (24dp + (2 * 12dp) = 48dp). Overflow button in narrower. The icon itself has a width of 12dp. Whole button’s width is 36dp: (12dp + (2 * 12dp) = 36dp).

In Toolbar implementation navigation button is significantly bigger than the others. Its size is 56dp x 56dp. View group which holds all action buttons has also the height of 56dp. It causes an issue in landscape mode on mobile phones described here. Action buttons themselves have proper sizing of 48dp x 48dp.

Overflow button has proper size too, but from misunderstood reasons, icon inside is moved closer to the left edge. Probably to try keeping right keyline, but that’s a nasty hack, and it’s also not close enough to the 16dp padding.

Toolbar title should be aligned to the second keyline with is 72dp on mobile. I know, that it’s as simple as setting contentInsetStart to the keyline value, but a lot of redesigned apps in Google Play Store (including Play Store, Photos, Keep etc.) have Toolbar title just next to navigation icon.

It’s even worse on tablets. The toolbar is not properly aligned at all!

Design:

Source: http://www.google.com/design/spec/layout/structure.html#structure-app-bar

And implementation:

Basically, it’s the same layout. Only one difference is height. It increased to 64dp. There is no navigation icon alignment to 24dp from the left edge. No overflow button alignment to 24dp from the right. No title alignment to 80dp keyline.

When I had dug deeper, I found a very similar problem in the implementation of support Actionbar and Actionbar in ActionMode (for example when you select text in EditText view, Actionbar starts ActionMode with buttons to copy and paste selected text).

Making it right

So let’s clean this mess, shall we? The good news is, it can be fixed. Better, it can be fixed with very little amount of work. All we need to do, it’s override few themes and styles.

First we have to override “toolbarStyle” and “toolbarNavigationButtonStyle” from Theme.AppCompat.

<style name=”Theme.GuidelinesCompat.Light.DarkToolbar” parent=”Theme.AppCompat.Light.DarkActionBar”>     ...     <!— Toolbar styles -->
<item name=”toolbarStyle”>@style/Custom.Widget.Toolbar</item>
<item name=”toolbarNavigationButtonStyle”>
@style/Custom.Widget.Toolbar.Button.Navigation</item>
</style>
<style name=”Custom.Widget.Toolbar” parent=”Widget.AppCompat.Toolbar”> <item name=”maxButtonHeight”>48dp</item>
<item name=”android:paddingLeft”>
@dimen/toolbar_horizontal_padding</item>
<item name=”android:paddingRight”>
@dimen/toolbar_horizontal_padding</item>
<item name=”contentInsetStart”>
@dimen/first_keyline</item>
</style><style name=”Custom.Widget.Toolbar.Button.Navigation” parent=”Widget.AppCompat.Toolbar.Button.Navigation”> <item name=”android:minWidth”>48dp</item></style>

To align Toolbar we need additional padding on both sides. The goal is to align navigation icon and overflow icon to 16dp from edge on mobile, and 24dp on tablet. Icon itself has 12dp padding, so 16dp — 12dp = 4dp padding on mobile and 24dp — 12dp = 12dp on tablet devices.

Here are necesary resources:

mobile: values/dimens.xml

<resources>     <dimen name=”first_keyline”>16dp</dimen>
<dimen name=”second_keyline”>72dp</dimen>
<dimen name=”toolbar_horizontal_padding”>4dp</dimen>
</resources>

tablet: values-sw600dp/dimens.xml

<resources>     <dimen name=”first_keyline”>24dp</dimen>
<dimen name=”second_keyline”>80dp</dimen>
<dimen name=”toolbar_horizontal_padding”>12dp</dimen>
</resources>

Now it’s time for overflow button. In Theme.Appcompat there’s separate value for “minWidth” of this button. And it’s correct. 36dp. But there’s also a weird padding. Bigger on right side, than on the left. And even bigger on both sides in tablet folder. Let’s get rid of them.

<style name=”Theme.GuidelinesCompat.Light.DarkToolbar” parent=”Theme.AppCompat.Light.DarkActionBar”>     ...     <!— Toolbar styles -->     <item name=”toolbarStyle”>@style/Custom.Widget.Toolbar</item>
<item name=”toolbarNavigationButtonStyle”>
@style/Custom.Widget.Toolbar.Button.Navigation</item>
<item name=”actionOverflowButtonStyle”>
@style/Custom.Widget.ActionButton.Overflow</item>
</style><style name=”Custom.Widget.ActionButton.Overflow” parent=”Widget.AppCompat.ActionButton.Overflow”> <item name=”android:paddingLeft”>0dp</item>
<item name=”android:paddingRight”>0dp</item>
</style>

When navigation icon is used “contentInsetStart” value should be equal second keyline. It can be setted as view attribute.

layout/layout.xml

<android.support.v7.widget.Toolbar
android:id=”@+id/toolbar”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:minHeight=”?attr/actionBarSize”
android:elevation=”6dp”
android:background=”@color/colorPrimary”
app:navigationIcon=”@drawable/ic_menu_white_24dp”
app:contentInsetStart=”@dimen/second_keyline”
app:theme=”@style/Theme.GuidelinesCompat.DarkToolbar”
app:popupTheme=”@style/Toolbar.Popup.AppCompat” />

Action Mode

Next step is to fix Actionbar in Action Mode. So once again — custom styles.

<!— GuidelinesCompat application theme --><style name=”Theme.GuidelinesCompat.Light.DarkToolbar” parent=”Theme.AppCompat.Light.DarkToolbar”>     <item name=”windowActionModeOverlay”>true</item>     <!— Action Mode styles -->     <item name=”actionModeStyle”>
@style/Custom.Widget.ActionMode</item>
<item name=”actionModeCloseButtonStyle”>
@style/Custom.Widget.ActionButton.CloseMode</item>
...</style><style name=”Custom.Widget.ActionMode” parent=”Widget.AppCompat.ActionMode”> <item name=”android:paddingLeft”>
@dimen/toolbar_h_padding</item>
<item name=”android:paddingRight”>
@dimen/toolbar_h_padding</item>
</style><style name=”Custom.Widget.ActionButton.CloseMode” parent=”Widget.AppCompat.ActionButton.CloseMode”> <item name=”android:layout_marginRight”>20dp</item></style>

Layout of Action Mode differs from Toolbar. To keep its title aligned to second keyline, close button needs right margin of 20dp. It’s odd, but it’s the only solution.

To sum up

As you can see it’s really easy to upgrade Toolbar to whole new level. I hope a lot of you guys see this huge difference.

I would love to see apps which applied this changes. Of course, you can check sample app on my Github.

Read next

If you want to know a little bit more about Material Design tips for developers read my next article.

Case Study. Master/Detail Pattern Revisited

.

--

--

Lucas Urbas

Android developer. UI/UX enthusiast. Nomadic lifestyle