While an app's first and foremost task is to display meaningful content to users and let them do various operations within it, it is equally important for it to be easily navigatable -- with a clear screen name, a logo or in some cases a subtitle.

An Android application (generally) is a set of activities that are stitched together to give a unified experience to users. Take for example WhatsApp. It has got a home activity where three tabs are located, then there's a chat activity that hosts chat details, and so on. All these are connected to one another by Intents that are fired on certain clicks by the user as well by the back navigation buttons -- the default (physical and on-screen) one and the one ( <-- ) in the toolbar. Each of these activities has a component at the top, a view group, that hosts the activity title, in some cases the subtitle, the logo, some activity-specific menu options such as search and so on. This component is our ActionBar.

A sample demonstration of action bar with the menu button and title.

Wait a minute!  What's an action bar and weren't we going to talk about the toolbar in this article? Sure, we are going to, but we need to understand the action bar first as the toolbar is the generalization of the action bar that is free to be used at any level within the activity, unlike action bar which is controlled by the Android framework itself tagging it at the top of the activity screen. Let's see what an ActionBar and Toolbar are and how different toolbar elements are used, and how to set up a toolbar as an action bar.

0. What's ActionBar and how does it differ?

With API level 11 or the Android 3.0 Honeycomb, the ActionBar was introduced. An action bar is simply a view group that holds the activity title on the left and the menu options on the right giving all the activities that use the default theme a consistent feel. Here are the key functions of the action bar,

  1. A dedicated space for giving your app an identity and indicating the user's location in the app.
  2. Access to important actions in a predictable way, such as search.
  3. Support for navigation and view switching (with tabs or drop-down lists).

An action bar can interchangeably be called an app bar as well or a Toolbar if you choose to call it that. Toolbar, as mentioned earlier, is simply a generalization of the ActionBar, which essentially gives the same experience, but is much more customizable with no hierarchy restriction and new design elements such as AppBarLayout and CollapsingToolbarLayout. We won't be talking about these two in this article, so if you want you can read about them here.

On the topic of key differences, there's hardly a point other than the freedom to put Toolbar at any location down the hierarchy. Put it within CollapsingToolbarLayout and you get a native collapsing toolbar with animations. The other point we can make regarding this is that a Toolbar must be set as an ActionBar to get the different options that an action bar provides with. Default options on the right (the three vertical dots in the picture), the default navigation button on the left (start) of the toolbar and more are ActionBar specific. If you chose not to set Toolbar as the action bar, you will miss out on these features. However, all those can easily be implemented manually if you need a  custom Toolbar with fine-grained control. Image buttons, vector images, and done!

1. What's a Toolbar

The Toolbar is a ViewGroup (extends it) that is used within an activity to display related information and options such as search or select all. Optionally, the toolbar can also be set as the ActionBar using setSupportActionBar(...)

While I have already emphasized the key differences between the toolbar and action bar, it's worth mentioning why Toolbar was introduced in the first place, what key functions it provides with other than ones by ActionBar. A few of the key attributes provided by Toolbar are,

  1. A navigation button: This button lies on the left of the Toolbar and must be used for navigational purposes within the activity such as closing, or moving back or drawer menu toggle. Toolbar keeps this button vertically aligned within the toolbar's set minimum height.
  2. A branded logo image: Some activities need a branded logo attached to the header just before the title to make it more appealing. With Toolbar, we need not add an extra ImageView for branding, that comes preloaded.
  3. A title and subtitle: Most activities need a title in the header to inform the user of the current screen (or context). While a title is common in the header, a subtitle is somewhat suited for a small set of use cases such as showing user's presence in a chat (WhatsApp?). If a subtitle is absent, the title is kept vertically aligned, otherwise, the set of both is kept aligned vertically within the minimum height of the Toolbar.
  4. An action menu:  Just like the navigation button of the left, an optional action menu can also be added to the toolbar that sits on the right vertically aligned within its container. An action menu generally includes important or relevant actions for the activity.
  5. One or more custom views: A toolbar can also contain child views, which I know isn't the general idea due to its satisfying set of functions -- it's a ViewGroup after all. Hybrid applications such as the Instagram use a slightly different style of Toolbar, no action or navigation buttons at all, instead, they put custom views (ImageButtons) in the toolbar (if they still use the toolbar). We will see more about custom views in a bit. Just remember to look for app namespace in XML for component (Toolbar) level attributes.

All few key functions of the above come with component-level XML and Java setters. We will now dive into the part where we see how to handle toolbar setters well, and what can be avoided. But first, let's add the dependency needed for Toolbar.

2. Adding Toolbar to application

Adding the following dependency to our application's build.gradle (Module: app) will include the Toolbar library (support v7) for our use. Just keep in mind to replace the appcompat version at the end of the dependency to match your compileSdk version and run gradle.

implementation 'com.android.support:appcompat-v7:26.1.0'

Also, remember to use,

android.support.v7.widget.Toolbar

 in order to support the maximum number of devices, not android.widget.Toolbar which is supported by API level 21 (Lollipop) and above.

Then, once gradle is done, add the following to your Activity's XML, 

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?android:attr/actionBarSize"
    android:background="#fff"
    android:elevation="2dp" />

This piece of code adds a standard blank-white toolbar to your Activity. Most of the attributes it has are self-explanatory and are found in most of the components. However, we need to address one small detail in the code -- the layout height value that is,

?android:attr/actionBarSize

Android framework has a set of predefined attr values which can be used in the app as well. actionBarSize's value is 56dp, which is the recommended height for action bar (toolbar). Use it in place of an arbitrary value that looks okay to make sure your toolbar appears consistent.

3. Title and Subtitle

Title and subtitle both play a significant role in delivering current context to the user. While Title is generally used for giving a name to the activity, it's subtitle's role to deliver more relevant content to the user about the activity. Add the following to Toolbar XML,

app:title="My Title"
app:subtitle="This a demo subtitle"

or do this in your activity,

toolbar.setTitle([CharSequence, int]);
toolbar.setSubtitle([CharSequence, int]);

 and your title appears on the left with subtitle just below it.

The title comes with 3 more supporting attributes while the subtitle has got 2. One of the attributes is text color which applies helps apply custom color to both title and subtitle. Use these two attributes to set text color,

app:subtitleTextColor="#555555"
app:titleTextColor="#333333"

or

toolbar.setSubtitleTextColor(Color.parseColor("#555555"));
toolbar.setTitleTextColor(Color.parseColor("#333333"));

The other common attribute is text appearance that allows for the default appearance to change with custom styles just like these,

app:subtitleTextAppearance="@style/TextAppearance.AppCompat.Subhead"
app:titleTextAppearance="@style/TextAppearance.AppCompat.Headline"

or

toolbar.setSubtitleTextAppearance(this,R.style.TextAppearance_AppCompat_Subhead);
toolbar.setTitleTextAppearance(this,R.style.TextAppearance_AppCompat_Headline);

The only non-common attribute is margin which is title exclusive. The toolbar offers several attributes to set margins on the title, from left to top. The one thing to take is that we need to use titleMargin, not titleMargins which is now deprecated like this,

app:titleMargin="5dp"
app:titleMarginTop="5dp"

or

toolbar.setTitleMargin(15, 15, 15, 15);
toolbar.setTitleMarginTop(15);

The only difference between the Java setter and XML setter is that Java setter accepts values in pixels, not in a defined unit like dp or sp. So, we must first convert the value to pixels as per device density and then pass them to setters.

One more thing related to the toolbar logo, title, and subtitle is that they have a default padding from the start -- precisely 16dp which exists even with the nav button. So, if there is a need to change the padding value, you can always use these,

app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"

or in a case where navigation button might be needed, use this instead,

app:contentInsetStartWithNavigation="0dp"

Of course, I have used 0dp here, but you can select any other value as per the need. And yes, this is effective for the whole set of the logo, title, and subtitle -- meaning they all have the same padding from the start.

4. Navigation

As I mentioned above, the Toolbar also adds navigation ability to the activity, more specifically the ability to open a menu drawer or close an event or the activity itself.

The navigation icon that we set appears on the left within the toolbar and is kept at a margin of 16dp from the start.

app:navigationIcon="@drawable/ic_menu"
app:navigationContentDescription="Navigation button description"

or

toolbar.setNavigationIcon([Drawable, int]);
toolbar.setNavigationContentDescription([CharSequence, int]);

The other setter you see above, navigation content description, allows you to set a description for the navigation button (icon) to be used in accessibility services such as screen readers.

The other thing to keep in mind while setting a navigation button is that it occupies an area of 56x56 (dp) -- 24dp icon and 16dp margin on both sides, and then the title (or the icon) aligns itself on its right at a margin of 16dp. That's a total of 72dp from the start.

On mobile, Android uses 16dp margin on both ends, the same goes for toolbar as well. 

Now, if we want to use this navigation button, we can use it in two ways -- using a click listener for the button (toolbar attribute) or set the toolbar as action bar and use navigation button as Home Up button.

# Navigation Button - On Click Listener

The Toolbar provides a native click listener for the navigation button that can be used for closing an activity (finish?) or calling out drawer layout or jumping to an activity through intent. The following code snippet demonstrates the use of nav click listener for finishing an activity (or simply jumping back to the last activity).

toolbar.setNavigationOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(MainActivity.this, "End of Activity!", Toast.LENGTH_LONG).show();
        finish();
    }
});

Just replace the part inside onClick method to suit your needs.

# Home Up Button

The home up button can be activated by setting Toolbar as the ActionBar and then enabling home up like this,

setSupportActionBar(toolbar);
// Access the support ActionBar
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

One thing that we need to note here is that unlike Navigation Click Listener,  Home Up doesn't offer an interface to use for custom use. A click will simply take the user back to the parent (home) activity that we define in the manifest. 

Defining parent activity is easy. Just add the attributeparentActivityName and pass the activity you want to act as the home as its value. Here, we have got,

android:parentActivityName="com.contextneutral.myapp.MyChildActivity"

which is setting our home activity for the activity, MySecondActivity. With that, we have set our home activity for Android 4.1 or above. To support the versions below that, we need to add a metadata within the activity tag with a name and value, like this,

<meta-data
   android:name="android.support.PARENT_ACTIVITY"
   android:value="com.contextneutral.myapp.MainActivity" />

We have used the same activity we passed above for the home activity. Once done, the whole activity tag block must appear like this,

<activity
     android:name="com.contextneutral.myapp.MySecondActivity" android:parentActivityName="com.contextneutral.myapp.MainActivity" >
   
     <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.contextneutral.myapp.MainActivity" /> </activity>

Well, we are done with manifest set up. We can now jump to home activity from this second activity.

However, if you want to jump to different activities based on different conditions, you can ignore adding parent activity name and rather use, 

@Override
  public boolean onOptionsItemSelected(MenuItem item) {
     
     if (item.getItemId() == android.R.id.home) {
        //go to an activity or end this activity with finish
        finish();
     }

     return super.onOptionsItemSelected(item);
}

This method can be overridden in the Activity and is triggered when a menu item is clicked/selected in the toolbar/action bar. This method is triggered whether you set a parent activity for the activity or not. Now, focus on the if clause. We take out the item id (menu item, in this case) and check if it equals to,

android.R.id.home

which is our home up button id. If it does match, just end the activity or push to any other activity as per need. The same method, above, will be required for other action (menu on the right) buttons in the toolbar.

One thing that we must note here is that at once either the navigation button will work or the up button -- once navigation click listener is registered, only it will get triggered, not the home up. Also, if using navigation click listener, please set the toolbar as action bar before adding code for the listener as the opposite will clear the nav listener.

5. Adding Actions / Menu Items

Actions are Toolbar specific menu item driven events that users can opt for the current context (activity?). Look below -- the following toolbar hosts 2 visible menu items and one in the overflow -- these are our action buttons, aligned to the right of the parent, toolbar. Here, we have just assumed the users will use these 2 more than the third one in the overflow. 

Toolbar with 2 menu items and an overflow menu button.

So, how do we add these three buttons and how to put the lesser required one in the overflow? Well, the answer involves three simple steps,

  1. Setting Toolbar as ActionBar
  2. Creating and inflating menu items
  3. Handling menu item clicks

These three steps and we will be in action. Let's discuss each one of the steps and find out how we can embed menu items into our header or simply toolbar and how we can listen to events.

# Setting Toolbar as ActionBar

Setting up the toolbar as action bar is important for the menu items to work or rather appear in the toolbar. We have already seen how we can do that so we will simply skip forward. 

setSupportActionBar(toolbar);

The point of doing this is that menu items are still being managed by old action bar methods that are tied to the activity and can be overridden for use which we will see in the next step. We don't get a separate API for toolbar menus, so we go with the ActionBar one. Once done, we can now create a menu layout and inflate it in the toolbar where it belongs just like we do with content layouts, we inflate them where needed.

# Creating and inflating menu items

Now that we are done with our action bar set up, we can move forward to creating a new menu layout and then after we inflate it to make it visible in the toolbar, aligned to the right.

In order to create a menu layout, we first need to create a new menu resource directory in the res folder. If you already have the menu res directory in your app, skip forward to the next paragraph. You must already know the res folder. A right-click on it will open a host of options, just go through new and then tap on Android Resource Directory. A window will pop out as a result. Just change the resource type to menu and press ok, leave everything as it is. You will see the menu directory appear within res hierarchy.

Once done, right-click on menu >> new >> menu resource file and we have a new window pop up asking for file's name. Just name the file anything you desire in lowercase and hit ok. The file we just created will open as a result. This is our menu layout where we put our menu items within the menu tag block.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/search"
        android:icon="@drawable/ic_search_dark"
        android:title="Search"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/notifications"
        android:icon="@drawable/ic_notifications_dark"
        android:title="Notifications"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/share"
        android:title="share"
        app:showAsAction="never" />
</menu>

If you look above, we have added a few items in the block. Actually, look carefully -- we have three items, a search item, a notification one, and the third is share. But what's the difference among the three?

Well, there are several differences but the one to be noticed is the attribute with the namespace app. The attribute showAsAction is responsible for the item to appear depending on the value passed as well the conditions mentioned. The attribute accepts 5 values,

  1. always: Will always show the menu item on the action bar.
  2. never: Item will appear in the overflow menu.
  3. ifRoom: Will show on the action bar if there is space available or will move to the overflow menu.
  4. withText: Will show the item with both icon and text (title). However won't display the text if room not available, just the icon.
  5. collapseActionView: Will display the actionView widget as an icon if on the action bar (room available for it) or as a simple item if in the overflow. More on actionView widget later.

What we have done in out menu layout is that we have set two items to show always but the third to never appear or rather stay in the overflow.

The other attributes of the menu items are self-explanatory -- title takes text title, id is for identification of the item, and icon takes an icon.

Okay, so we have our menu layout prepared, now we need to make it appear. For that, we will inflate the layout. We need to override the following method in our Activity class,

@Override
public boolean onCreateOptionsMenu(Menu menu) {
  // the inflation code goes here
  return super.onCreateOptionsMenu(menu);
}

and once done, we can add the following to inflate the menu layout,

MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.default_menu, menu);

What we have done above is create a MenuInflater object and use its inflate method to do the inflating. The inflate method accepts two parameters, first is the id of menu layout with the other being Menu object that we get from the overridden method. The final result will look something like this,

@Override
public boolean onCreateOptionsMenu(Menu menu) {
  MenuInflater inflater = getMenuInflater();
  inflater.inflate(R.menu.default_menu, menu);
  return super.onCreateOptionsMenu(menu);
}

# Handling menu item clicks

Handling action is as easy as it was to inflate the menu layout. We will be overriding another method, specifically this one,

boolean onOptionsItemSelected(MenuItem item)

which gets triggered when a menu item is selected. The method offers the item (MenuItem) which we will use to extract the id and based on that id, we will perform an action -- as simple as that.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
   int id = item.getItemId();
        
   switch (id) {
      case R.id.search: 
          // open search activity
          break;
      case R.id.notifications: 
          // show notifications
          break;
     case R.id.share:
          //open share dialog
          break;

   }
   return super.onOptionsItemSelected(item);
}

Just one thing to remember here is that we need to use the same id as we declared back in the item (layout XML).

6. Summary

With actions, we sum up this story. We got to know what action bar and toolbar are, how they differ and how they both can be used together as well. We also learned about a number of toolbar attributes such as title, different buttons, margins etc,  that make our lives easier. We got to know about navigation features and how to enable them and make use of them, and how to set up actions in the toolbar.

While we have discussed most of the attributes and features of the Toolbar, we have left a few deliberately for the next part where we talk about advanced features that revolve around collapsing toolbar and more.

If you found this article worthy of your read time, please be sure to share it or recommending it to others.