1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
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 as defined by {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}.</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:
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>
|