page.title=Providing Up Navigation page.tags=up navigation,NavUtils,TaskStackBuilder trainingnavtop=true @jd:body
EffectiveNavigation.zip
All screens in your app that are not the main entrance to your app (the "home" screen) should offer the user a way to navigate to the logical parent screen in the app's hierarchy by pressing the Up button in the action bar. This lesson shows you how to properly implement this behavior.
Up Navigation Design
The concepts and principles for Up navigation are described in Designing Effective Navigation and the Navigation design guide.
To implement Up navigation, the first step is to declare which activity is the appropriate parent for each activity. Doing so allows the system to facilitate navigation patterns such as Up because the system can determine the logical parent activity from the manifest file.
Beginning in Android 4.1 (API level 16), you can declare the logical parent of each
activity by specifying the {@code
android:parentActivityName} attribute
in the {@code
If your app supports Android 4.0 and lower, include the
Support Library with your app and
add a {@code
For example:
<application ... > ... <!-- The main/home activity (it has no parent activity) --> <activity android:name="com.example.myfirstapp.MainActivity" ...> ... </activity> <!-- A child of the main activity --> <activity android:name="com.example.myfirstapp.DisplayMessageActivity" android:label="@string/title_activity_display_message" android:parentActivityName="com.example.myfirstapp.MainActivity" > <!-- Parent activity meta-data to support 4.0 and lower --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.example.myfirstapp.MainActivity" /> </activity> </application>
With the parent activity declared this way, you can navigate Up to the appropriate parent using the {@link android.support.v4.app.NavUtils} APIs, as shown in the following sections.
To allow Up navigation with the app icon in the action bar, call {@link android.app.ActionBar#setDisplayHomeAsUpEnabled setDisplayHomeAsUpEnabled()}:
{@literal @}Override public void onCreate(Bundle savedInstanceState) { ... getActionBar().setDisplayHomeAsUpEnabled(true); }
This adds a left-facing caret alongside the app icon and enables it as an action button such that when the user presses it, your activity receives a call to {@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()}. The ID for the action is {@code android.R.id.home}.
To navigate up when the user presses the app icon, you can use the {@link android.support.v4.app.NavUtils} class's static method, {@link android.support.v4.app.NavUtils#navigateUpFromSameTask navigateUpFromSameTask()}. When you call this method, it finishes the current activity and starts (or resumes) the appropriate parent activity. If the target parent activity is in the task's back stack, it is brought forward. The way it is brought forward depends on whether the parent activity is able to handle an {@link android.app.Activity#onNewIntent onNewIntent()} call:
up
intent contains {@link
android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}, the parent activity is
brought to the top of the stack, and receives the intent through its
{@link android.app.Activity#onNewIntent onNewIntent()} method.up
intent does not contain
{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}, the parent activity
is popped off the stack, and a new instance of that activity is created on
top of the stack to receive the intent.For example:
{@literal @}Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { // Respond to the action bar's Up/Home button case android.R.id.home: NavUtils.navigateUpFromSameTask(this); return true; } return super.onOptionsItemSelected(item); }
However, using {@link android.support.v4.app.NavUtils#navigateUpFromSameTask navigateUpFromSameTask()} is suitable only when your app is the owner of the current task (that is, the user began this task from your app). If that's not true and your activity was started in a task that belongs to a different app, then navigating Up should create a new task that belongs to your app, which requires that you create a new back stack.
If your activity provides any intent filters that allow other apps to start the activity, you should implement the {@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} callback such that if the user presses the Up button after entering your activity from another app's task, your app starts a new task with the appropriate back stack before navigating up.
You can do so by first calling {@link android.support.v4.app.NavUtils#shouldUpRecreateTask shouldUpRecreateTask()} to check whether the current activity instance exists in a different app's task. If it returns true, then build a new task with {@link android.support.v4.app.TaskStackBuilder}. Otherwise, you can use the {@link android.support.v4.app.NavUtils#navigateUpFromSameTask navigateUpFromSameTask()} method as shown above.
For example:
{@literal @}Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { // Respond to the action bar's Up/Home button case android.R.id.home: Intent upIntent = NavUtils.getParentActivityIntent(this); if (NavUtils.shouldUpRecreateTask(this, upIntent)) { // This activity is NOT part of this app's task, so create a new task // when navigating up, with a synthesized back stack. TaskStackBuilder.create(this) // Add all of this activity's parents to the back stack .addNextIntentWithParentStack(upIntent) // Navigate up to the closest parent .startActivities(); } else { // This activity is part of this app's task, so simply // navigate up to the logical parent activity. NavUtils.navigateUpTo(this, upIntent); } return true; } return super.onOptionsItemSelected(item); }
Note: In order for the {@link
android.support.v4.app.TaskStackBuilder#addNextIntentWithParentStack addNextIntentWithParentStack()}
method to work,
you must declare the logical parent of each activity in your manifest file, using the
{@code
android:parentActivityName} attribute (and corresponding {@code