1 page.title=Providing Up Navigation 2 page.tags=up navigation,NavUtils,TaskStackBuilder 3 4 trainingnavtop=true 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> 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> 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> 21 <li><a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back Stack</a></li> 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 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> 50 51 52 <img src="{@docRoot}images/training/implementing-navigation-up.png" id="figure-up"> 53 <p class="img-caption"><strong>Figure 1.</strong> The <em>Up</em> button in the action bar.</p> 54 55 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 72 <a href="{@docRoot}tools/support-library/index.html">Support Library</a> with your app and 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> 112 113 <pre> 114 {@literal @}Override 115 public void onCreate(Bundle savedInstanceState) { 116 ... 117 getActionBar().setDisplayHomeAsUpEnabled(true); 118 } 119 </pre> 120 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. The way it is brought forward depends on whether the parent activity 137 is able to handle an {@link 138 android.app.Activity#onNewIntent onNewIntent()} call:</p> 139 140 <ul> 141 <li>If the parent activity has launch mode <a 142 href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code 143 <singleTop>}</a>, or the <code>up</code> intent contains {@link 144 android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}, the parent activity is 145 brought to the top of the stack, and receives the intent through its 146 {@link android.app.Activity#onNewIntent onNewIntent()} method.</li> 147 148 <li>If the parent activity has launch mode <a 149 href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code 150 <standard>}</a>, and the <code>up</code> intent does not contain 151 {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}, the parent activity 152 is popped off the stack, and a new instance of that activity is created on 153 top of the stack to receive the intent.</li> 154 </ul> 155 156 <p>For example:</p> 157 158 <pre> 159 {@literal @}Override 160 public boolean onOptionsItemSelected(MenuItem item) { 161 switch (item.getItemId()) { 162 // Respond to the action bar's Up/Home button 163 case android.R.id.home: 164 NavUtils.navigateUpFromSameTask(this); 165 return true; 166 } 167 return super.onOptionsItemSelected(item); 168 } 169 </pre> 170 171 <p>However, using {@link android.support.v4.app.NavUtils#navigateUpFromSameTask 172 navigateUpFromSameTask()} is suitable <strong>only when your app is the owner of the current 173 task</strong> (that is, the user began this task from your app). If that's not true and your 174 activity was started in a task that belongs to a different app, then 175 navigating <em>Up</em> should create a new task that belongs to your app, which 176 requires that you create a new back stack.</p> 177 178 <h3 id="BuildBackStack">Navigate up with a new back stack</h3> 179 180 <p>If your activity provides any <a 181 href="{@docRoot}guide/components/intents-filters.html#ifs">intent filters</a> 182 that allow other apps to start the 183 activity, you should implement the {@link android.app.Activity#onOptionsItemSelected 184 onOptionsItemSelected()} callback such that if the user presses the <em>Up</em> button 185 after entering your activity from another app's task, your app starts a new task 186 with the appropriate back stack before navigating up.</p> 187 188 <p>You can do so by first calling 189 {@link android.support.v4.app.NavUtils#shouldUpRecreateTask shouldUpRecreateTask()} to check 190 whether the current activity instance exists in a different app's task. If 191 it returns true, then build a new task with {@link android.support.v4.app.TaskStackBuilder}. 192 Otherwise, you can use the {@link android.support.v4.app.NavUtils#navigateUpFromSameTask 193 navigateUpFromSameTask()} method as shown above.</p> 194 195 <p>For example:</p> 196 197 <pre> 198 {@literal @}Override 199 public boolean onOptionsItemSelected(MenuItem item) { 200 switch (item.getItemId()) { 201 // Respond to the action bar's Up/Home button 202 case android.R.id.home: 203 Intent upIntent = NavUtils.getParentActivityIntent(this); 204 if (NavUtils.shouldUpRecreateTask(this, upIntent)) { 205 // This activity is NOT part of this app's task, so create a new task 206 // when navigating up, with a synthesized back stack. 207 TaskStackBuilder.create(this) 208 // Add all of this activity's parents to the back stack 209 .addNextIntentWithParentStack(upIntent) 210 // Navigate up to the closest parent 211 .startActivities(); 212 } else { 213 // This activity is part of this app's task, so simply 214 // navigate up to the logical parent activity. 215 NavUtils.navigateUpTo(this, upIntent); 216 } 217 return true; 218 } 219 return super.onOptionsItemSelected(item); 220 } 221 </pre> 222 223 <p class="note"><strong>Note:</strong> In order for the {@link 224 android.support.v4.app.TaskStackBuilder#addNextIntentWithParentStack addNextIntentWithParentStack()} 225 method to work, 226 you must declare the logical parent of each activity in your manifest file, using the 227 <a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code 228 android:parentActivityName}</a> attribute (and corresponding <a 229 href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> element) 230 as described above.</p> 231