Saturday, December 20, 2014

Using the Android Toolbar Widget

    Introduced with Android Lollipop, the Toolbar is meant to be a replacement for the ActionBar when additional customization is required. In this tutorial I will go over some of the basic customizations for the Toolbar and how to customize it with some styles. All code for this tutorial can be found on GitHub.

    The first thing we're going to want to do is import the AppCompat library in build.gradle, as this'll provide the support version of the Toolbar back to Android API 7.

compile 'com.android.support:appcompat-v7:21.0.3'

    Once we have the library imported, we can add the Toolbar to our activity layout file. One of the biggest advantages to using the Toolbar widget is that you can place the view anywhere in your layout. For this example we'll just keep it at the top of the layout, like the standard ActionBar. One thing to note is that the Toolbar extends ViewGroup, so the layout file can also contain additional views if needed.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        style="@style/AppTheme.Toolbar" />

    <TextView
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"/>

</LinearLayout>

    Now that the activity layout is built, we need to adjust the theme used for the activity to exclude the default ActionBar, as it is not compatible with a Toolbar. This same theme can be used to customize some general features of the Toolbar, such as the background color, text color and overflow popup theme. The following styles will provide us with a green Toolbar and overflow dropdown, white text and white overflow button color.

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

        <!-- Used for Toolbar background color -->
        <item name="colorPrimary">#005500</item>
        <!-- Toolbar + Overflow menu text color -->
        <item name="android:textColorPrimary">#FFFFFF</item>
        <!-- Overflow menu button color -->
        <item name="android:textColorSecondary">#FFFFFF</item>

    </style>

    <style name="AppTheme.Toolbar" parent="Widget.AppCompat.Toolbar">
        <item name="android:background">?attr/colorPrimary</item>
        <item name="android:minHeight">?attr/actionBarSize</item>
        <item name="popupTheme">@style/AppTheme.ActionBar.Popup</item>
    </style>

    <!-- Overflow drop down style -->
    <style name="AppTheme.ActionBar.Popup" parent="Widget.AppCompat.Light.PopupMenu.Overflow">
        <item name="android:background">?attr/colorPrimary</item>
    </style>


    With the layout and styles applied, we can start applying the logic behind our Toolbar. To start, we declare the Toolbar and a custom view that will be added to the Toolbar, in this case an AnalogClock (mainly because it's really obvious/visible for this example), at the top of our activity

    private Toolbar mToolbar;
    private AnalogClock mCustomView;

    After the ContentView has been set to our layout file, we can initialize the Toolbar and call setSupportActionBar() to assign the Toolbar to our activity.

        mToolbar = (Toolbar) findViewById( R.id.toolbar );
        setSupportActionBar( mToolbar );

    The overflow menu is populated in the same way that you would populate the ActionBar, by inflating a menu xml file in onCreateOptionsMenu() and handling the actions in onOptionsItemSelected(). For this example we'll use the actions in the overflow menu to call methods for customizing the Toolbar.


    From this point, the rest of the Toolbar actions are fairly straight forward. The Toolbar title, subtitle and logo can be set with a few method calls from getSupportActionBar().

    private void showCustomTitleAndSubtitle() {
        getSupportActionBar().setTitle( "Custom Title");
        getSupportActionBar().setSubtitle( "subtitle" );
        getSupportActionBar().setDisplayShowTitleEnabled( true );
    }

    private void hideTitleAndSubtitle() {
        getSupportActionBar().setDisplayShowTitleEnabled( false );
    }

    private void showDefaultLogo() {
        getSupportActionBar().setLogo( R.drawable.ic_launcher );
        getSupportActionBar().setDisplayUseLogoEnabled( true );
    }

    private void hideLogo() {
        getSupportActionBar().setDisplayUseLogoEnabled( false );
    }


     Adding and removing a custom view to the Toolbar is equally straight forward. The biggest thing to remember is that we need to attempt to remove the custom view from our Toolbar first, otherwise the app will crash if we attempt to add the same view to the Toolbar more than once. Once we're certain that the custom view is not attached to our Toolbar, we can the view and our Toolbar will automatically update.

    private void showCustomView() {
        if( mCustomView == null )
            mCustomView = (AnalogClock) LayoutInflater.from( this ).inflate( R.layout.ab_clock, null );

        mToolbar.removeView( mCustomView );
        mToolbar.addView( mCustomView );
    }

    private void hideCustomView() {
        mToolbar.removeView( mCustomView );
        setSupportActionBar( mToolbar );
    }


    With that, we have a Toolbar that is easily customizable, able to be placed anywhere in our layout and easily styled to fit our app color scheme.

4 comments:

  1. Thank you for this great tutorial. How do you i implement ontabselected and ontabunselected using this tutorial?

    ReplyDelete
  2. Hi Paul,

    I am just wondering is there a way to set the subtitle, logo etc for the toolbar by mentioning them in the XML itself. Looks like you need to add them at runtime only, i.e., programmatically.

    Thanks
    Ganesh

    ReplyDelete
  3. Thanks for sharing, this has helped out a lot. One problem that I am having with custom views is when I hide it, and subsequently call setSupportActionBar( mToolbar ), my navigation drawer toggle is no longer working. Any idea why this would no longer work and what I have to do to fix it?

    ReplyDelete
    Replies
    1. You know, I'm not really sure if I've ever run into that issue. I'd check to see if anyone else has, and if it's possibly a bug with the Toolbar class.

      Delete