Grokking Android

Getting Down to the Nitty Gritty of Android Development

Adding ActionViews to Your ActionBar

By

As you have seen in the previous tutorials about ActionBarSherlock and the ActionBar, you can add action items easily and they show up either in the ActionBar itself or in the overflow menu.

But so far all you could add were normal action items. And those consisted either of icons, of text or of a combination of both - depending on the available space and of the way you configured the items to show up.

That's not always sufficient. Sometimes you would like to display a custom layout. And that's what ActionViews are for.

What are ActionViews

Action views allow to display arbitrary layouts instead of the usual icons or texts. They were introduced in Honeycomb together with the ActionBar.

Of course the available place for your layout limits your possibilities. Since - by a large margin - most Android devices are phones, your layout should take this into consideration.

With Ice Cream Sandwich ActionViews were improved further. Since then Android does not always display them fully expanded but allows for a collapsed mode as well. In this mode ActionViews show an icon as usual and only when the user clicks on the icon does it expand to the full layout.

When to use ActionViews

Basically you use ActionViews when you need to replace the icon with something else or when you need a more interactive widget.

Android itselfs comes bundled with the SearchView that adds an EditText widget for search. I will cover this widget in the next section.

Another common use case is to replace an action item with a progress indicator when the action is bound to last longer. Most often this is used together with a refresh action item.

Using Android's SearchView

Android comes with the SearchView as the only bundled implementation of an ActionView.

I covered all you need to know about searching on Android and search suggestions in previous tutorials. Here I will cover only how to make use of the SearchView.

Let me first show you some screenshots:

Collapsed Searchview showing only the search icon
Collapsed Searchview showing only the search icon
Expanded Searchview showing the EditText field together with the search icon and the search hint
Expanded Searchview showing the EditText field together with the search icon and the search hint
Expanded SearchView with entered text
Expanded SearchView with entered text

The first shows the action bar with the search icon - thus the action view is in collapsed mode. The second screenshot shows the view after the user has clicked on the icon. It expands to an EditText widget together with the search hint of your searchable configuration. The microphone symbol is also the result of the search configuration file. The last screen shows the EditText widget after the user has entered some characters.

If you have added search capabilities to your app, getting the SearchView to support this is pretty easy. All you have to do is tell it about the search configuration. For this you need to get a SearchableInfo object from the SearchManager and call setSearchableInfo() with this object on the SearchView object used for your ActionBar. Well for me code is often the best explanation, so here is what you have to do:


@Override
public boolean onCreateOptionsMenu(Menu menu) {
   getSupportMenuInflater().
         inflate(R.menu.activity_actionview, menu);
   MenuItem item = menu.findItem(R.id.actionView);
   SearchView searchView = 
         (SearchView)item.getActionView();
   SearchManager searchManager = 
         (SearchManager)getSystemService(Context.SEARCH_SERVICE);
   SearchableInfo info = 
         searchManager.getSearchableInfo(getComponentName());
   searchView.setSearchableInfo(info);
   return true;
}

You should understand most of it from my previous tutorial on ActionBarSherlock. New are the lines 6 to 11. These are where you add your search configuration to the SearchView.

As you can see in the code above, I use the SearchView together with ActionBarSherlock. ActionBarSherlock added a SearchView with its 4.2 release. As a deviation from ABS' normal API level 7 support, the SearchView only work from API level 8 onwards. The reason for this is that the SearchableInfo interface was added with API level 8. So a support for a SearchView prior to that makes no sense.

The version in ActionBarSherlock's 4.2 release had some problems with search suggestions. These were fixed by Matt Kranzler's accepted pull request to ABS. But this fix is currently only available in the dev branch of ActionBarSherlock.

Update: With the 4.3 release of ActionBarSherlock suggestions now work. So if you want to use them, you have to include ActionBarSherlock 4.3 (or any follow-up releases).

The next screenshot shows the suggestions provider at work with ActionBarSherlock's dev branch fixes on a 2.2 device:

Suggestions working in ActionBarSherlock when using the dev branch
Suggestions working in ActionBarSherlock when using the dev branch

Be very careful, if you use this branch. After all the current development is taking place here. It's not yet finalized for production!

A custom ActionView

As mentioned you can also create arbitrary action views. You have some options to do so:

I do not cover the last one. That's because it's the least likely solution for you and also because I haven't yet covered how to create custom views in Android in this blog.

So let me show you how to use the first two.

Linking to a layout file

In this case you create a layout file and point to it directly from within your menu xml file:


<item 
   android:id="@+id/actionViewLayout"
   android:showAsAction="ifRoom|collapseActionView"
   android:icon="@drawable/ic_action_add"
   android:title="Add"
   android:actionLayout="@layout/activity_actionview_edittext"
/>

In line six you can see how the layout is referenced directly from within the menu item definition.

You still have the option to show it in expanded or in collapsed mode right from the outset. Line three in the xml snippet above uses a collapsed mode at first. The difference becomes obvious in the next screenshots. The first set shows the item in collapsed mode first. When you press the add item, Android expands the layout and moves all other action items into the overflow menu.

The add Actionview in collapsed mode
The add Actionview in collapsed mode
Add ActionView in expanded mode
Add ActionView in expanded mode

If you use the layout expanded all the time, it's present all the time and takes up the place it needs. All other action items are visible - as long as some place is left for them. That's what you see in the next screenshot. This option is the most space-constrained option you have. If your ActionView is always expanded, you probably have not much room left for any other action items. That's the reason I use a landscape screenshot. So make sure you use the value ifRoom for the android:showAsAction attributes of all the other items - and to limit the action view to as little space as absolutely necessary.

ActionView expanded right away
ActionView expanded right away

To use the expanded view all the time you simply have to remove the collapseActionView value and the pipe symbol from line 3 of above's xml snippet.

Of course it depends on the use case at hand and what your layout is, but I think this option generally is best used with an expanded layout all the time. Otherwise users might get confused by the disappearing action items when they expand the layout. And users might not know that they can use the back button to collapse the view again. If you plan to expand the layout on an action item click you're probably better off with the option of the next paragraph.

Setting the layout when the user clicks the item

This option combines both methods of the former paragraph. Once again two screenshots demonstrate best what I am talking about:

Refresh ActionView in collapsed mode
Refresh ActionView in collapsed mode
Refresh icon replaced by ProgressBar spinner
Refresh icon replaced by ProgressBar spinner

The first screenshot shows the refresh icon as a normal action item. The layout file looks like any other menu item:


<item
   android:id="@+id/progress"
   android:icon="@drawable/ic_action_reload"
   android:showAsAction="ifRoom"
   android:title="@string/progress"
/>

But as soon as you click the refresh button, Android replaces it with the progress spinner. That's because I set an action view in reaction to the action item click. The first code shows the onOptionsItemSelected() method in which I react to the item click:


@Override
public boolean onOptionsItemSelected(MenuItem item) {
   if (item.getItemId() == R.id.progress) {
      new DummyAsyncTask().execute((Void[])null);
      return true;
   }
   return super.onOptionsItemSelected(item);
}

The AsyncTask is a sample implementation showing you how to change the action view values:


private class DummyAsyncTask extends 
      AsyncTask<Void, Void, Void> {

   @Override
   protected Void doInBackground(Void... params) {
      // simulate doing some time-consuming stuff:
      SystemClock.sleep(2000);
      return null;
   }
   @Override
   protected void onPostExecute(Void result) {
      super.onPostExecute(result);
      ActionViewActivity.this.mProgress.setActionView(null);
   }   
   @Override
   protected void onPreExecute() {
      super.onPreExecute();
      ActionViewActivity.this.mProgress.
            setActionView(R.layout.activity_actionview_progress);
   }
}

As soon as the work is done and the new values have been downloaded, you simply set the action view to null again - in the code above I do this in the onPostExecute() method.

As you can see it uses an expanded mode - but only for the time, the user actually needs this view. Do not use the value collapseActionView in your menu item definition. Otherwise the layout expands on the left of the ActionBar and not in place of the icon!

Sample app

You can find the source of a sample app demonstrating all this on bitbucket. I'm more than happy if you spot any problems with the code and provide a pull request. You can also file an issue on the project page.

Lessons learned

In this tutorial you have seen how to make use of ActionViews. Very useful is the SearchView - thus I detailed how to add this to your ActionBar and how to link it to your search configuration in this post.

You have also seen that in the current 4.2 release of ActionBarSherlock SearchSuggestions are not yet working correctly. But thanks to a fix those will be part of the next ABS release.

Finally you learned how to create an ActionView on your own, though use cases for this are limited. Probably the most common one is replacing an update icon with the progress spinner widget.

Wolfram Rittmeyer lives in Germany and has been developing with Java for many years.

He has been interested in Android for quite a while and has been blogging about all kind of topics around Android.

You can find him on Google+ and Twitter.