1page.title=Providing Proper Back Navigation 2page.tags=back navigation,NavUtils,TaskStackBuilder 3 4trainingnavtop=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="#SynthesizeBackStack">Synthesize a new Back Stack for Deep Links</a></li> 14 <li><a href="#back-fragments">Implement Back Navigation for Fragments</a></li> 15 <li><a href="#back-webviews">Implement Back Navigation for WebViews</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</div> 26</div> 27 28 29<p><em>Back</em> navigation is how users move backward through the history of screens 30they previously visited. All Android devices provide a <em>Back</em> button for this 31type of navigation, so <strong>your app should not add a Back button to the UI</strong>.</p> 32 33<p>In almost all situations, the system maintains a back stack of activities while the user 34navigates your application. This allows the system to properly navigate backward when the user 35presses the <em>Back</em> button. However, there are a few cases in which your app should manually 36specify the <em>Back</em> behavior in order to provide the best user experience.</p> 37 38<div class="note design"> 39<p><strong>Back Navigation Design</strong></p> 40<p>Before continuing with this document, you should understand the 41concepts and principles for <em>Back</em> navigation as described in 42the <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> design 43guide.</p> 44</div> 45 46<p>Navigation patterns that require you to manually specify the <em>Back</em> behavior include:</p> 47<ul> 48 <li>When the user enters a deep-level activity directly from a <a 49 href="{@docRoot}guide/topics/ui/notifiers/notifications.html">notification</a>, an <a 50 href="{@docRoot}guide/topics/appwidgets/index.html">app widget</a>, or the <a 51 href="{@docRoot}training/implementing-navigation/nav-drawer.html">navigation drawer</a>.</li> 52 <li>Certain cases in which the user navigates between <a 53 href="{@docRoot}guide/components/fragments.html">fragments</a>.</li> 54 <li>When the user navigates web pages in a {@link android.webkit.WebView}.</li> 55</ul> 56 57<p>How to implement proper <em>Back</em> navigation in these situations is described 58in the following sections.</p> 59 60 61 62<h2 id="SynthesizeBackStack">Synthesize a new Back Stack for Deep Links</h2> 63 64<p>Ordinarily, the system incrementally builds the back stack as the user navigates from one 65activity to the next. However, when the user enters your app with a <em>deep link</em> that 66starts the activity in its own task, it's necessary for you to synthesize a new 67back stack because the activity is running in a new task without any back stack at all.</p> 68 69<p>For example, when a notification takes the user to an activity deep in your app hierarchy, 70you should add activities into your task's back stack so that pressing <em>Back</em> navigates 71up the app hierarchy instead of exiting the app. This pattern is described further in the 72<a href="{@docRoot}design/patterns/navigation.html#into-your-app" 73>Navigation</a> design guide.</p> 74 75 76<h3 id="SpecifyParent">Specify parent activities in the manifest</h3> 77 78<p>Beginning in Android 4.1 (API level 16), you can declare the logical parent of each 79activity by specifying the <a 80href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code 81android:parentActivityName}</a> attribute 82in the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code 83<activity>}</a> element. This allows the system to facilitate navigation patterns 84because it can determine the logical <em>Back</em> or <em>Up</em> navigation path with this 85information.</p> 86 87<p>If your app supports Android 4.0 and lower, include the 88<a href="{@docRoot}tools/support-library/index.html">Support Library</a> with your app and 89add a <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> 90element inside the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code 91<activity>}</a>. Then specify the parent activity as the value 92for {@code android.support.PARENT_ACTIVITY}, matching the <a 93href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code 94android:parentActivityName}</a> attribute.</p> 95 96<p>For example:</p> 97 98<pre> 99<application ... > 100 ... 101 <!-- The main/home activity (it has no parent activity) --> 102 <activity 103 android:name="com.example.myfirstapp.MainActivity" ...> 104 ... 105 </activity> 106 <!-- A child of the main activity --> 107 <activity 108 android:name="com.example.myfirstapp.DisplayMessageActivity" 109 android:label="@string/title_activity_display_message" 110 android:parentActivityName="com.example.myfirstapp.MainActivity" > 111 <!-- The meta-data element is needed for versions lower than 4.1 --> 112 <meta-data 113 android:name="android.support.PARENT_ACTIVITY" 114 android:value="com.example.myfirstapp.MainActivity" /> 115 </activity> 116</application> 117</pre> 118 119<p>With the parent activity declared this way, you can use the 120{@link android.support.v4.app.NavUtils} APIs to synthesize a new back stack by identifying which 121activity is the appropriate parent for each activity.</p> 122 123 124 125<h3 id="CreateBackStack">Create back stack when starting the activity</h3> 126 127<p>Adding activities to the back stack begins upon the event that takes the user into your app. 128That is, instead of calling {@link android.content.Context#startActivity startActivity()}, use the 129{@link android.support.v4.app.TaskStackBuilder} APIs to define each activity that should 130be placed into a new back stack. Then begin the target activity by calling {@link 131android.support.v4.app.TaskStackBuilder#startActivities startActivities()}, or create the 132appropriate {@link android.app.PendingIntent} by calling {@link 133android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}.</p> 134 135<p>For example, when a notification takes the user to an activity deep in your app hierarchy, 136you can use this code to create a {@link android.app.PendingIntent} 137that starts an activity and inserts a new back stack into the target task:</p> 138 139<pre> 140// Intent for the activity to open when user selects the notification 141Intent detailsIntent = new Intent(this, DetailsActivity.class); 142 143// Use TaskStackBuilder to build the back stack and get the PendingIntent 144PendingIntent pendingIntent = 145 TaskStackBuilder.create(this) 146 // add all of DetailsActivity's parents to the stack, 147 // followed by DetailsActivity itself 148 .addNextIntentWithParentStack(upIntent) 149 .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); 150 151NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 152builder.setContentIntent(pendingIntent); 153... 154</pre> 155 156<p>The resulting {@link android.app.PendingIntent} specifies not only the activity to 157start (as defined by {@code detailsIntent}), but also the back stack that should be inserted 158into the task (all parents of the {@code DetailsActivity} defined by {@code detailsIntent}). 159So when the {@code DetailsActivity} starts, pressing <em>Back</em> 160navigates backward through each of the {@code DetailsActivity} class's parent activities.</p> 161 162<p class="note"><strong>Note:</strong> In order for the {@link 163android.support.v4.app.TaskStackBuilder#addNextIntentWithParentStack addNextIntentWithParentStack()} 164method to work, 165you must declare the logical parent of each activity in your manifest file, using the 166<a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">{@code 167android:parentActivityName}</a> attribute (and corresponding <a 168href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> element) 169as described above.</p> 170 171 172 173 174 175<h2 id="back-fragments">Implement Back Navigation for Fragments</h2> 176 177<p>When using fragments in your app, individual {@link android.app.FragmentTransaction} 178objects may represent context changes that should be added to the back stack. For example, if you 179are implementing a <a href="descendant.html#master-detail">master/detail flow</a> on a handset by 180swapping out fragments, you should ensure that pressing the <em>Back</em> button on a detail 181screen returns the user to the master screen. To do so, call {@link 182android.app.FragmentTransaction#addToBackStack addToBackStack()} before you commit 183the transaction:</p> 184 185<pre> 186// Works with either the framework FragmentManager or the 187// support package FragmentManager (getSupportFragmentManager). 188getSupportFragmentManager().beginTransaction() 189 .add(detailFragment, "detail") 190 // Add this transaction to the back stack 191 .addToBackStack() 192 .commit(); 193</pre> 194 195<p>When there are {@link android.app.FragmentTransaction} objects on the back stack and the user 196presses the <em>Back</em> button, 197the {@link android.app.FragmentManager} pops the most recent transaction off the back stack and 198performs the reverse action (such as removing a fragment if the transaction added it).</p> 199 200<p class="note"><strong>Note:</strong> You <strong>should not add transactions to the back 201stack</strong> when the transaction is for horizontal navigation (such as when switching tabs) 202or when modifying the content appearance (such as when adjusting filters). For more information, 203about when <em>Back</em> navigation is appropriate, 204see the <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> design guide.</p> 205 206<p>If your application updates other user interface elements to reflect the current state of your 207fragments, such as the action bar, remember to update the UI when you commit the transaction. You 208should update your user interface after the back stack changes in addition to 209when you commit the transaction. You can listen for when a {@link android.app.FragmentTransaction} 210is reverted by setting up an {@link android.app.FragmentManager.OnBackStackChangedListener}:</p> 211 212<pre> 213getSupportFragmentManager().addOnBackStackChangedListener( 214 new FragmentManager.OnBackStackChangedListener() { 215 public void onBackStackChanged() { 216 // Update your UI here. 217 } 218 }); 219</pre> 220 221 222 223<h2 id="back-webviews">Implement Back Navigation for WebViews</h2> 224 225<p>If a part of your application is contained in a {@link android.webkit.WebView}, it may be 226appropriate for <em>Back</em> to traverse browser history. To do so, you can override {@link 227android.app.Activity#onBackPressed onBackPressed()} and proxy to the 228{@link android.webkit.WebView} if it has history state:</p> 229 230<pre> 231{@literal @}Override 232public void onBackPressed() { 233 if (mWebView.canGoBack()) { 234 mWebView.goBack(); 235 return; 236 } 237 238 // Otherwise defer to system default behavior. 239 super.onBackPressed(); 240} 241</pre> 242 243<p>Be careful when using this mechanism with highly dynamic web pages that can grow a large 244history. Pages that generate an extensive history, such as those that make frequent changes to 245the document hash, may make it tedious for users to get out of your activity.</p> 246 247<p>For more information about using {@link android.webkit.WebView}, read <a 248href="{@docRoot}guide/webapps/webview.html">Building Web Apps in WebView</a>. 249