Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 1 | page.title=Providing Up Navigation |
Scott Main | 0c39152 | 2013-05-15 14:38:16 -0700 | [diff] [blame] | 2 | page.tags="up navigation","NavUtils","TaskStackBuilder" |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 3 | |
| 4 | trainingnavtop=true |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 5 | |
| 6 | @jd:body |
| 7 | |
| 8 | <div id="tb-wrapper"> |
| 9 | <div id="tb"> |
| 10 | |
| 11 | <h2>This lesson teaches you to:</h2> |
| 12 | <ol> |
Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 13 | <li><a href="#SpecifyParent">Specify the Parent Activity</a></li> |
| 14 | <li><a href="#up">Add Up Action</a></li> |
| 15 | <li><a href="#NavigateUp">Navigate Up to Parent Activity</a></li> |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 16 | </ol> |
| 17 | |
| 18 | <h2>You should also read</h2> |
| 19 | <ul> |
| 20 | <li><a href="{@docRoot}training/design-navigation/ancestral-temporal.html">Providing Ancestral and Temporal Navigation</a></li> |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 21 | <li><a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back Stack</a></li> |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 22 | <li><a href="{@docRoot}design/patterns/navigation.html">Android Design: Navigation</a></li> |
| 23 | </ul> |
| 24 | |
| 25 | <h2>Try it out</h2> |
| 26 | |
| 27 | <div class="download-box"> |
| 28 | <a href="http://developer.android.com/shareables/training/EffectiveNavigation.zip" |
| 29 | class="button">Download the sample app</a> |
| 30 | <p class="filename">EffectiveNavigation.zip</p> |
| 31 | </div> |
| 32 | |
| 33 | </div> |
| 34 | </div> |
| 35 | |
| 36 | |
Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 37 | <p>All screens in your app that are not the main entrance to your app (the "home" screen) |
| 38 | should offer the user a way to navigate to the logical parent screen in the app's hierarchy by |
| 39 | pressing the <em>Up</em> button in the <a |
| 40 | href="{@docRoot}guide/topics/ui/actionbar.html">action bar</a>. |
| 41 | This lesson shows you how to properly implement this behavior.</p> |
| 42 | |
| 43 | <div class="note design"> |
| 44 | <p><strong>Up Navigation Design</strong></p> |
| 45 | <p>The concepts and principles for <em>Up</em> navigation are described in <a |
| 46 | href="{@docRoot}training/design-navigation/ancestral-temporal.html">Designing Effective |
| 47 | Navigation</a> and the <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> design |
| 48 | guide.</p> |
| 49 | </div> |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 50 | |
| 51 | |
Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 52 | <img src="{@docRoot}images/training/implementing-navigation-up.png" id="figure-up"> |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 53 | <p class="img-caption"><strong>Figure 1.</strong> The <em>Up</em> button in the action bar.</p> |
| 54 | |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 55 | |
Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 56 | |
| 57 | <h2 id="SpecifyParent">Specify the Parent Activity</h2> |
| 58 | |
| 59 | <p>To implement <em>Up</em> navigation, the first step is to declare which activity is the |
| 60 | appropriate parent for each activity. Doing so allows the system to facilitate navigation patterns |
| 61 | such as <em>Up</em> because the system can determine the logical parent activity from |
| 62 | the manifest file.</p> |
| 63 | |
| 64 | <p>Beginning in Android 4.1 (API level 16), you can declare the logical parent of each |
| 65 | activity by specifying the <a |
| 66 | href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code |
| 67 | android:parentActivityName}</a> attribute |
| 68 | in the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> |
| 69 | element.</p> |
| 70 | |
| 71 | <p>If your app supports Android 4.0 and lower, include the |
Scott Main | 4e2c9dc | 2013-07-23 19:35:17 -0700 | [diff] [blame] | 72 | <a href="{@docRoot}tools/support-library/index.html">Support Library</a> with your app and |
Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 73 | add a <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> |
| 74 | element inside the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code |
| 75 | <activity>}</a>. Then specify the parent activity as the value |
| 76 | for {@code android.support.PARENT_ACTIVITY}, matching the <a |
| 77 | href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code |
| 78 | android:parentActivityName}</a> attribute.</p> |
| 79 | |
| 80 | <p>For example:</p> |
| 81 | |
| 82 | <pre> |
| 83 | <application ... > |
| 84 | ... |
| 85 | <!-- The main/home activity (it has no parent activity) --> |
| 86 | <activity |
| 87 | android:name="com.example.myfirstapp.MainActivity" ...> |
| 88 | ... |
| 89 | </activity> |
| 90 | <!-- A child of the main activity --> |
| 91 | <activity |
| 92 | android:name="com.example.myfirstapp.DisplayMessageActivity" |
| 93 | android:label="@string/title_activity_display_message" |
| 94 | android:parentActivityName="com.example.myfirstapp.MainActivity" > |
| 95 | <!-- Parent activity meta-data to support 4.0 and lower --> |
| 96 | <meta-data |
| 97 | android:name="android.support.PARENT_ACTIVITY" |
| 98 | android:value="com.example.myfirstapp.MainActivity" /> |
| 99 | </activity> |
| 100 | </application> |
| 101 | </pre> |
| 102 | |
| 103 | <p>With the parent activity declared this way, you can navigate <em>Up</em> |
| 104 | to the appropriate parent using the {@link android.support.v4.app.NavUtils} APIs, as shown in |
| 105 | the following sections.</p> |
| 106 | |
| 107 | |
| 108 | <h2 id="up">Add Up Action</h2> |
| 109 | |
| 110 | <p>To allow <em>Up</em> navigation with the app icon in the action bar, call |
| 111 | {@link android.app.ActionBar#setDisplayHomeAsUpEnabled setDisplayHomeAsUpEnabled()}:</p> |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 112 | |
| 113 | <pre> |
| 114 | {@literal @}Override |
| 115 | public void onCreate(Bundle savedInstanceState) { |
| 116 | ... |
| 117 | getActionBar().setDisplayHomeAsUpEnabled(true); |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 118 | } |
| 119 | </pre> |
| 120 | |
Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 121 | <p>This adds a left-facing caret alongside the app icon and enables it as an action button |
| 122 | such that when the user presses it, your activity receives a call to |
| 123 | {@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()}. The |
| 124 | ID for the action is {@code android.R.id.home}.</p> |
| 125 | |
| 126 | |
| 127 | |
| 128 | <h2 id="NavigateUp">Navigate Up to Parent Activity</h2> |
| 129 | |
| 130 | <p>To navigate up when the user presses the app icon, you can use the {@link |
| 131 | android.support.v4.app.NavUtils} class's static method, |
| 132 | {@link android.support.v4.app.NavUtils#navigateUpFromSameTask |
| 133 | navigateUpFromSameTask()}. When you call this method, it finishes the current activity and |
| 134 | starts (or resumes) the appropriate parent activity. |
| 135 | If the target parent activity is in the task's back stack, it is brought |
| 136 | forward as defined by {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}.</p> |
| 137 | |
| 138 | <p>For example:</p> |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 139 | |
| 140 | <pre> |
| 141 | {@literal @}Override |
| 142 | public boolean onOptionsItemSelected(MenuItem item) { |
| 143 | switch (item.getItemId()) { |
Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 144 | // Respond to the action bar's Up/Home button |
| 145 | case android.R.id.home: |
| 146 | NavUtils.navigateUpFromSameTask(this); |
| 147 | return true; |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 148 | } |
| 149 | return super.onOptionsItemSelected(item); |
| 150 | } |
| 151 | </pre> |
| 152 | |
Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 153 | <p>However, using {@link android.support.v4.app.NavUtils#navigateUpFromSameTask |
| 154 | navigateUpFromSameTask()} is suitable <strong>only when your app is the owner of the current |
| 155 | task</strong> (that is, the user began this task from your app). If that's not true and your |
| 156 | activity was started in a task that belongs to a different app, then |
| 157 | navigating <em>Up</em> should create a new task that belongs to your app, which |
| 158 | requires that you create a new back stack.</p> |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 159 | |
Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 160 | |
| 161 | <h3 id="BuildBackStack">Navigate up with a new back stack</h3> |
| 162 | |
| 163 | <p>If your activity provides any <a |
| 164 | href="{@docRoot}guide/components/intents-filters.html#ifs">intent filters</a> |
| 165 | that allow other apps to start the |
| 166 | activity, you should implement the {@link android.app.Activity#onOptionsItemSelected |
| 167 | onOptionsItemSelected()} callback such that if the user presses the <em>Up</em> button |
| 168 | after entering your activity from another app's task, your app starts a new task |
| 169 | with the appropriate back stack before navigating up.</p> |
| 170 | |
| 171 | <p>You can do so by first calling |
| 172 | {@link android.support.v4.app.NavUtils#shouldUpRecreateTask shouldUpRecreateTask()} to check |
| 173 | whether the current activity instance exists in a different app's task. If |
| 174 | it returns true, then build a new task with {@link android.support.v4.app.TaskStackBuilder}. |
| 175 | Otherwise, you can use the {@link android.support.v4.app.NavUtils#navigateUpFromSameTask |
| 176 | navigateUpFromSameTask()} method as shown above.</p> |
| 177 | |
| 178 | <p>For example:</p> |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 179 | |
| 180 | <pre> |
| 181 | {@literal @}Override |
| 182 | public boolean onOptionsItemSelected(MenuItem item) { |
| 183 | switch (item.getItemId()) { |
Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 184 | // Respond to the action bar's Up/Home button |
| 185 | case android.R.id.home: |
| 186 | Intent upIntent = NavUtils.getParentActivityIntent(this); |
| 187 | if (NavUtils.shouldUpRecreateTask(this, upIntent)) { |
| 188 | // This activity is NOT part of this app's task, so create a new task |
| 189 | // when navigating up, with a synthesized back stack. |
| 190 | TaskStackBuilder.create(this) |
| 191 | // Add all of this activity's parents to the back stack |
| 192 | .addNextIntentWithParentStack(upIntent) |
| 193 | // Navigate up to the closest parent |
| 194 | .startActivities(); |
| 195 | } else { |
| 196 | // This activity is part of this app's task, so simply |
| 197 | // navigate up to the logical parent activity. |
| 198 | NavUtils.navigateUpTo(this, upIntent); |
| 199 | } |
| 200 | return true; |
Roman Nurik | 19266f7 | 2012-03-12 21:48:47 -0700 | [diff] [blame] | 201 | } |
| 202 | return super.onOptionsItemSelected(item); |
| 203 | } |
| 204 | </pre> |
| 205 | |
Scott Main | 7c84055 | 2013-03-26 18:53:01 -0700 | [diff] [blame] | 206 | <p class="note"><strong>Note:</strong> In order for the {@link |
| 207 | android.support.v4.app.TaskStackBuilder#addNextIntentWithParentStack addNextIntentWithParentStack()} |
| 208 | method to work, |
| 209 | you must declare the logical parent of each activity in your manifest file, using the |
| 210 | <a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code |
| 211 | android:parentActivityName}</a> attribute (and corresponding <a |
| 212 | href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> element) |
| 213 | as described above.</p> |