Grokking Android

Getting Down to the Nitty Gritty of Android Development

ActionBarSherlock: Up Navigation

By

In this tutorial I am going to cover some initial thoughts on navigation. The ActionBar allows multiple navigation modes. In this post I state which navigation modes exist, how to get to the ActionBar object in the first place and how to deal with the so-called up navigation.

Less code than in the previous parts because code-wise there is not much to it. But the concept is the cause for user confusion mostly caused by inconsistent implementations. I hope this post helps to get you on track to implement the up navigation in a correct way so that users understand your app easily.

Back and up navigation is a topic that's always causing lot's of discussions. When in doubt, please go to the developers community on Google+ or the user experience equivalent of StackOverflow and discuss the way you want to use it and if this is correct or not. If you have technical issues, though, please use StackOverflow.

The structure of the ActionBar

Let me go back for a second and explain the way the ActionBar is partitioned. I follow the terminology of the ActionBar pattern page in Android's design guidelines here.

ActionBar of the detail screen on a 2.2 device
ActionBar of the detail screen on a 2.2 device

On the left side of the ActionBar is the app icon and possibly some indicator for the up navigation or the slide-out menu. Next comes the View control. This is often a text showing where you are. It could also contain tabs or a spinner as alternative means for navigating your app. Those elements are aligned to the left.

On the right side we have the action buttons followed by the action overflow - if an overflow menu is present.

What is important is to distinguish both areas. The left area is the part where you put navigational elements. Like moving up, tabs or a spinner. The right part is where you put actions that belong to the view. Like actions to add or delete elements, to update a list or for adding songs to your favorite lists.

I do not discuss those action items in this post. I have already described how to add action items and how to use the overflow menu. I probably cover the split ActionBar in another post and I will also deal with Action Providers and Action Views in a later post.

Navigation types of the ActionBar

Basically there are four types of navigation supported by the ActionBar pattern:

Accessing the ActionBar object

Before you can use any of the navigational modes, you need access to the ActionBar object, though. Since there is no public Javadoc page for the ActionBarSherlock library, I recommend to use the documentation of Android's own ActionBar class, if you need to know about methods or fields of the ActionBar class. ActionBarSherlock's class offers the exact same methods. Of course the signature is different since it uses ActionBarSherlock counterparts for any parameters or return values that use object of the ActionBar API - but should you migrate to ABS from a project that already makes use of the stock ActionBar, just changing the imports should suffice.

Using ActionBarSherlock you get the ActionBar object by calling getSupportActionBar() from within your SherlockActivity:


ActionBar actionBar = getSupportActionBar();

If your API target is at least API level 14 you could be tempted to use getActionBar() instead. After all this method appears first among the code-completion suggestions. But that won't work on older devices - which is the reason to use ActionBarSherlock in the first place. So do the right thing and always call getSupportActionBar()!

Gladly Lint reminds you to do so:


Class requires API level 11 (current min is 7): android.app.ActionBar

But Lint cannot do so, when you added the Annotation SuppressLint("NewApi") to your code - so better be careful right from the beginning.

The method getSupportActionBar() is not available for fragments. But you can get access to the activity by calling getSherlockActivity(). And from here you can go on as shown above.

Be very careful here as well. If you call getActivity() instead, you will get an object of type android.support.v4.app.FragmentActivity. Since this class doesn't have the getSupportActionBar() method you are even more prone to call the wrong method.

How does ActionBarSherlock's ActionBar relate to Android's ActionBar

ActionBarSherlock creates a wrapper to a native ActionBar object on all devices with an API level of at least 14 (ICS). And it creates a compatibility object for older devices. Both inherit from com.actionbarsherlock.app.ActionBar.

This is important to know. Because if you develop using an emulator or a device with a newer API level, you get away with being sloppy. Well, until you start to actually use an older device. When you start your app on an older device, your app will force close because of a NoSuchMethodError. Not too surprising, since the method getActionBar() was not available for Activities back then.

Navigating to the start screen

The ActionBar pattern has emerged before an official implementation existed. That's the common way patterns emerge. The very first post on Juhani Lehtimäki's excellent blog androiduipatterns.com shows some examples of apps that implemented the ActionBar in 2010. With the introduction of Honeycomb the Android team added the ActionBar to the API in 2011.

Back then it was all the rage to use the app icon as something akin to the home button or the logo on websites. It would get you immediately to the initial screen of the app. Of course back then it looked as if the dashboard would gain traction and so a click on the app icon would immediately bring you back to this hub. This all has changed, but you still could use the app icon that way.

But I advise not to use the home navigation model. Instead make use of the up navigation. Using the up model is the recommended pattern of Android's design guidelines. I explain the up navigation in the next section. The code for home navigation would be nearly identical (it's just another target Activity) - but you prefer to follow the guidelines anyway, don't you?

Up navigation

With Ice Cream Sandwich the Android team has introduced the so-called up affordance to the platform. Perceived affordance is a visual clue helping users understand what a certain element does. In this case the up affordance helps the user to understand that he is going up (or back) a hierarchical level.

To be honest: I am still not convinced that this button is a useful addition to the Android platform, but that's just me. In fact it's a common pattern found in many current apps, it's pushed by Google and it's recommended on the design site. It looks like this pattern has established itself firmly. Thus, I recommend to use it, despite my misgivings!

So what is up navigation?

Up means getting up a hierarchy level. If you go up a level you usually also go back a level, thus the affordance, this tiny little left pointing caret, is not as weirdly chosen as it might sound.

Let me give you an example: Say you have a list of items and select one item. The detail screen would be the next hierarchical level. Up in this case would go back to the list of items. That's what the app used in this series does so far. But apps often have multiple levels in their hierarchy. And using the up button can help users navigate the app faster - an important consideration in the mobile environment.

Before discussing this any further, let me first show you how to do this.

Adding the up affordance

Navigating within hierarchies means that the up affordance should be visible as soon as you navigate down one level. Which basically means that all screens after the initial screen of the app should sport the up affordance.

If you followed this series so far, you added the following lines to the ItemDetailActivity in the first part about using fragments and the support library:


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
   getActionBar().setDisplayHomeAsUpEnabled(true);
}

You had to add the if statement as a temporary workaround to make your project compile before you have added ActionBarSherlock to it. Remember that getActionBar() only works on newer devices.

Now that you have added ActionBarSherlock in the last post of this series, you can use getSupportActionBar() instead. And since this works on older devices as well, you can drop the if statement instead:


// Show the Up button in the action bar:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

Reacting to an up click

When a user clicks on the home button of your app (not the home button of your device), you should navigate to the Activity that is logically one hierarchy above the current one. You do so within the onOptionsItemSelected() method of your ItemDetailActivity. In fact the Android developer tools did that already when you created the project:


@Override
public boolean onOptionsItemSelected(MenuItem item) {
   switch (item.getItemId()) {
      case android.R.id.home:
         // This ID represents the Home or Up button. In the case of this
         // activity, the Up button is shown. Use NavUtils to allow users
         // to navigate up one level in the application structure. For
         // more details, see the Navigation pattern on Android Design:
         //
         // http://developer.android.com/design/patterns/navigation.html#up-vs-back
         //
         NavUtils.navigateUpTo(this,
               new Intent(this, ItemListActivity.class));
         return true;
   }
   return super.onOptionsItemSelected(item);
}

NavUtils' navigateUpTo() method takes care of setting the flag FLAG_ACTIVITY_CLEAR_TOP and finishing the current activity. This flag ensures that a previous instance of this Activity within your task stack is reused, if available, and removes any activities on top of that activity.

Disabling the home button on the initial screen

Now when you already are at the root level of your app, there is no more up navigation possible. Thus you should disable the home button and the up affordance.

Doing so is simple. Just call setHomeButtonEnabled() and pass in a false value. For the project you have created in this series the home Activity is your ItemListActivity. Thus add this line to the onCreate() method somewhere after your call to the super method.:


// disable the home button and the up affordance:
getSupportActionBar().setHomeButtonEnabled(false);

So how is up different to the back button?

From what I have said so far, you might think that up is nothing else than the usual back button. But that's not the case!

Both buttons can go back to the same screen, that's true, but that's not always the case.

Granted, for the app, you have developed so far in this mini-series, there is no difference between up and back. But most often you can get to a certain screen in your app in multiple ways. And that's when back and up start to behave differently.

Up takes you always to a defined point of the app: The previous point in the hierarchy - no matter how you got to this point. Back though follows the trail you have chosen in reverse.

This is even more important if your app offers exported Activities for use by other applications. In this case the user might get to a screen of your app from an external app.

Up would still bring him up a hierarchical level within your app. Back on the other hand should bring the user back to where he came from - in this case the other app.

Even within your own app there can be differences. Say you are creating a conference app. From the schedule view the user selects one talk. The detail screen of the talk also links to other talks which are related as well as to talks that are by the same speaker. The user now might follow those links and thus view multiple talks. Now to return to the schedule fast, the user simply clicks the up icon and goes back to the schedule. With the back button though she would have to use multiple clicks - depending on the number of talks she has viewed.

Be wary of bad examples!

Don't have a look at how other apps do it. Have a look at the design guide instead. There are way too many apps that do not behave correctly. There might be good reasons for doing so, but usually it adds to user confusion. It hurts the Android platform in general. Something you do not want to do, do you?

For example Google Play behaves incorrectly. You can go to the games category directly from the start screen. Or you can get there by going to apps and then selecting the games category. But up behaves differently, depending on where you came from. I can understand the reasoning behind it. They want to avoid confusion. But one level deeper the up button suddenly starts to work as up and not as back aynmore. What should users make of this?

As good-intentioned as this might be, I think it actually adds to the confusion. How should users grok the up button when it sometimes behaves incorrectly and works differently depending on where you are in the app? So, please, if you want to deviate from the guidelines, think twice. Think thrice. Discuss it with peers. Discuss it with usability experts. Do some users tests! Do your users and us all this favor!

What about the slide-out menu?

When discussing how to add the up affordance I said that you shouldn't show an up affordance and that the home button shouldn't be enabled when the user is on the initial screen of your app.

Obviously that's not the case for the YouTube app, not for the Google+ app and an increasing number of other apps. YouTube as well as Google+ show the up affordance on the home screen and when you press the app icon again, the so-called slide-out menu appears. This is a relatively new pattern that has replaced the dashboard.

The slide-out menu has its name because it appears in a slide-out motion from the left side of the screen. It can be accessed using the up button - and sometimes by using a bezel-swipe from the left.

Keep in mind that this pattern is highly controversial. Jake Wharton, the creator of ActionBarSherlock, for example is a strong opponent of it. I personally like it, though I agree that it has some shortcomings. But with this in mind, carefully think whether your app needs one or not. Do not just add one, because it seems to be en-vogue right now. 🙂

I won't deal with this pattern here. There is a short paragraph on the ActionBar pattern page in the design guide. And you can find a detailed presentation of the slide-out navigation pattern on Juhani's androiduipatterns.com site.

What you need to know is, that the trigger for this menu with regards to the ActionBar is also the up button. You react to it as described above. Of course you do not simply start a new Activity but have to show the menu instead. One library to help you do so is Jeremy Feinstein's SlidingMenu library. Of course, there are others as well, but I happen to like this one.

Lessons learned

In this post you learned about the up navigation and how to implement it. You added the up affordance to one activity and disabled the home button on the other one.

You also learned what the difference between up and back is and how well-intentioned deviations from the standard can cause user confusion.

I didn't cover how to properly deal with Widget or Notification clicks to your app. I am totally opposed to the recommended behavior and probably would rant too much. Well actually this might be a topic for another post so as to vent off a bit and explain why I don't like it 🙂   But not in this series.

I also left out how to create a new task and a simulated back stack when using the up button after a user got to your app from another app. I might do so in some other post if the need arises. But currently I think it's explained sufficiently in the Android training class about ancestral navigation. The current app is too simple to explain this properly.

Has this post helped you? Do you have any more questions about up vs. back? Let me know about questions left open, any remarks you want to make or any mistakes you have spotted in the comment section.

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.