| page.title=Providing Up Navigation | |
| page.tags=up navigation,NavUtils,TaskStackBuilder | |
| trainingnavtop=true | |
| @jd:body | |
| <div id="tb-wrapper"> | |
| <div id="tb"> | |
| <h2>This lesson teaches you to:</h2> | |
| <ol> | |
| <li><a href="#SpecifyParent">Specify the Parent Activity</a></li> | |
| <li><a href="#up">Add Up Action</a></li> | |
| <li><a href="#NavigateUp">Navigate Up to Parent Activity</a></li> | |
| </ol> | |
| <h2>You should also read</h2> | |
| <ul> | |
| <li><a href="{@docRoot}training/design-navigation/ancestral-temporal.html">Providing Ancestral and Temporal Navigation</a></li> | |
| <li><a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back Stack</a></li> | |
| <li><a href="{@docRoot}design/patterns/navigation.html">Android Design: Navigation</a></li> | |
| </ul> | |
| <h2>Try it out</h2> | |
| <div class="download-box"> | |
| <a href="http://developer.android.com/shareables/training/EffectiveNavigation.zip" | |
| class="button">Download the sample app</a> | |
| <p class="filename">EffectiveNavigation.zip</p> | |
| </div> | |
| </div> | |
| </div> | |
| <p>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 <em>Up</em> button in the <a | |
| href="{@docRoot}guide/topics/ui/actionbar.html">action bar</a>. | |
| This lesson shows you how to properly implement this behavior.</p> | |
| <div class="note design"> | |
| <p><strong>Up Navigation Design</strong></p> | |
| <p>The concepts and principles for <em>Up</em> navigation are described in <a | |
| href="{@docRoot}training/design-navigation/ancestral-temporal.html">Designing Effective | |
| Navigation</a> and the <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> design | |
| guide.</p> | |
| </div> | |
| <img src="{@docRoot}images/training/implementing-navigation-up.png" id="figure-up"> | |
| <p class="img-caption"><strong>Figure 1.</strong> The <em>Up</em> button in the action bar.</p> | |
| <h2 id="SpecifyParent">Specify the Parent Activity</h2> | |
| <p>To implement <em>Up</em> 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 <em>Up</em> because the system can determine the logical parent activity from | |
| the manifest file.</p> | |
| <p>Beginning in Android 4.1 (API level 16), you can declare the logical parent of each | |
| activity by specifying the <a | |
| href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code | |
| android:parentActivityName}</a> attribute | |
| in the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> | |
| element.</p> | |
| <p>If your app supports Android 4.0 and lower, include the | |
| <a href="{@docRoot}tools/support-library/index.html">Support Library</a> with your app and | |
| add a <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> | |
| element inside the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code | |
| <activity>}</a>. Then specify the parent activity as the value | |
| for {@code android.support.PARENT_ACTIVITY}, matching the <a | |
| href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code | |
| android:parentActivityName}</a> attribute.</p> | |
| <p>For example:</p> | |
| <pre> | |
| <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> | |
| </pre> | |
| <p>With the parent activity declared this way, you can navigate <em>Up</em> | |
| to the appropriate parent using the {@link android.support.v4.app.NavUtils} APIs, as shown in | |
| the following sections.</p> | |
| <h2 id="up">Add Up Action</h2> | |
| <p>To allow <em>Up</em> navigation with the app icon in the action bar, call | |
| {@link android.app.ActionBar#setDisplayHomeAsUpEnabled setDisplayHomeAsUpEnabled()}:</p> | |
| <pre> | |
| {@literal @}Override | |
| public void onCreate(Bundle savedInstanceState) { | |
| ... | |
| getActionBar().setDisplayHomeAsUpEnabled(true); | |
| } | |
| </pre> | |
| <p>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}.</p> | |
| <h2 id="NavigateUp">Navigate Up to Parent Activity</h2> | |
| <p>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:</p> | |
| <ul> | |
| <li>If the parent activity has launch mode <a | |
| href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code | |
| <singleTop>}</a>, or the <code>up</code> 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.</li> | |
| <li>If the parent activity has launch mode <a | |
| href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code | |
| <standard>}</a>, and the <code>up</code> 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.</li> | |
| </ul> | |
| <p>For example:</p> | |
| <pre> | |
| {@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); | |
| } | |
| </pre> | |
| <p>However, using {@link android.support.v4.app.NavUtils#navigateUpFromSameTask | |
| navigateUpFromSameTask()} is suitable <strong>only when your app is the owner of the current | |
| task</strong> (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 <em>Up</em> should create a new task that belongs to your app, which | |
| requires that you create a new back stack.</p> | |
| <h3 id="BuildBackStack">Navigate up with a new back stack</h3> | |
| <p>If your activity provides any <a | |
| href="{@docRoot}guide/components/intents-filters.html#ifs">intent filters</a> | |
| 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 <em>Up</em> button | |
| after entering your activity from another app's task, your app starts a new task | |
| with the appropriate back stack before navigating up.</p> | |
| <p>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.</p> | |
| <p>For example:</p> | |
| <pre> | |
| {@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); | |
| } | |
| </pre> | |
| <p class="note"><strong>Note:</strong> 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 | |
| <a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code | |
| android:parentActivityName}</a> attribute (and corresponding <a | |
| href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> element) | |
| as described above.</p> |