1 page.title=Action Bar 2 parent.title=User Interface 3 parent.link=index.html 4 @jd:body 5 6 <div id="qv-wrapper"> 7 <div id="qv"> 8 9 <h2>Quickview</h2> 10 <ul> 11 <li>A title bar that includes the application icon and activity title</li> 12 <li>Provides access to menu items and navigation modes such as tabs</li> 13 <li>Requires API level 11 or greater</li> 14 </ul> 15 16 <h2>In this document</h2> 17 <ol> 18 <li><a href="#Adding">Adding the Action Bar</a> 19 <ol> 20 <li><a href="#Removing">Removing the action bar</a></li> 21 </ol> 22 </li> 23 <li><a href="#ActionItems">Adding Action Items</a> 24 <ol> 25 <li><a href="#ChoosingActionItems">Choosing your action items</a></li> 26 <li><a href="#SplitBar">Using split action bar</a></li> 27 </ol> 28 </li> 29 <li><a href="#Home">Using the App Icon for Navigation</a> 30 <ol> 31 <li><a href="#Up">Navigating up</a></li> 32 </ol> 33 </li> 34 <li><a href="#ActionView">Adding an Action View</a> 35 <ol> 36 <li><a href="#ActionViewCollapsing">Handling collapsible action views</a></li> 37 </ol> 38 </li> 39 <li><a href="#ActionProvider">Adding an Action Provider</a> 40 <ol> 41 <li><a href="#ShareActionProvider">Using the ShareActionProvider</a></li> 42 <li><a href="#CreatingActionProvider">Creating a custom action provider</a></li> 43 </ol> 44 </li> 45 <li><a href="#Tabs">Adding Navigation Tabs</a></li> 46 <li><a href="#Dropdown">Adding Drop-down Navigation</a></li> 47 <li><a href="#Style">Styling the Action Bar</a> 48 <ol> 49 <li><a href="#GeneralStyles">General appearance</a></li> 50 <li><a href="#ActionItemStyles">Action items</a></li> 51 <li><a href="#NavigationStyles">Navigation tabs</a></li> 52 <li><a href="#DropDownStyles">Drop-down lists</a></li> 53 <li><a href="#AdvancedStyles">Advanced styling</a></li> 54 </ol> 55 </li> 56 </ol> 57 58 <h2>Key classes</h2> 59 <ol> 60 <li>{@link android.app.ActionBar}</li> 61 <li>{@link android.view.Menu}</li> 62 <li>{@link android.view.ActionProvider}</li> 63 </ol> 64 65 <h2>Related samples</h2> 66 <ol> 67 <li><a 68 href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a></li> 69 <li><a 70 href="{@docRoot}resources/samples/ActionBarCompat/index.html">Action Bar Compatibility</a></li> 71 <li><a 72 href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#ActionBar"> 73 API Demos</a></li> 74 </ol> 75 76 <h2>See also</h2>item 77 <ol> 78 <li><a href="{@docRoot}guide/topics/ui/menus.html">Menus</a></li> 79 <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Supporting Tablets 80 and Handsets</a></li> 81 </ol> 82 </div> 83 </div> 84 85 <p>The action bar is a window feature that identifies the application and user location, and 86 provides user actions and navigation modes. You should use the action bar in most activities that 87 need to prominently present user actions or global navigation, because the action bar offers users a 88 consistent interface across applications and the system gracefully adapts the action bar's 89 appearance for different screen configurations. You can control the behaviors and visibility of the 90 action bar with the {@link android.app.ActionBar} APIs, which were added in Android 3.0 (API level 91 11).</p> 92 93 <p>The primary goals of the action bar are to:</p> 94 95 <ul> 96 <li>Provide a dedicated space for identifying the application brand and user location. 97 <p>This is accomplished with the app icon or logo on the left side and the activity title. 98 You might choose to remove the activity title, however, if the current view is identified by a 99 navigation label, such as the currently selected tab.</p></li> 100 101 <li>Provide consistent navigation and view refinement across different applications. 102 <p>The action bar provides built-in tab navigation for switching between <a 103 href="{@docRoot}guide/topics/fundamentals/fragments.html">fragments</a>. It also offers a drop-down 104 list you can use as an alternative navigation mode or to refine the current view (such as to sort 105 a list by different criteria).</p> 106 </li> 107 108 <li>Make key actions for the activity (such as "search", "create", "share", etc.) prominent and 109 accessible to the user in a predictable way. 110 <p>You can provide instant access to key user actions by placing items from the <a 111 href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">options menu</a> directly in the action bar, 112 as "action items." Action items can also provide an "action view," which provides an embedded 113 widget for even more immediate action behaviors. Menu items that are not promoted 114 to an action item are available in the overflow menu, revealed by either the device MENU button 115 (when available) or by an "overflow menu" button in the action bar (when the device does not 116 include a MENU button).</p> 117 </li> 118 </ul> 119 120 <img src="{@docRoot}images/ui/actionbar.png" alt="" /> 121 <p class="img-caption"><strong>Figure 1.</strong> Action bar from the <a 122 href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a> app (on a 123 landscape handset), showing the logo on the left, navigation tabs, and an action item on the 124 right (plus the overflow menu button).</p> 125 126 127 <div class="sidebox-wrapper"> 128 <div class="sidebox"> 129 <h2>Remaining backward-compatible</h2> 130 <p>If you want to provide an action bar in your application <em>and</em> remain compatible with 131 versions of Android older than 3.0, you need to create the action bar in your 132 activity's layout (because the {@link android.app.ActionBar} class is not available on older 133 versions).</p> 134 <p>To help you, the <a 135 href="{@docRoot}resources/samples/ActionBarCompat/index.html">Action Bar Compatibility</a> sample 136 app provides an API layer and action bar layout that allows your app to use some of the {@link 137 android.app.ActionBar} APIs and also support older versions of Android by replacing the traditional 138 title bar with a custom action bar layout.</p> 139 </div> 140 </div> 141 142 143 <h2 id="Adding">Adding the Action Bar</h2> 144 145 <p>Beginning with Android 3.0 (API level 11), the action bar is included in all 146 activities that use the {@link android.R.style#Theme_Holo Theme.Holo} theme (or one of its 147 descendants), which is the default theme when either the <a 148 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> or 149 <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> 150 attribute is set to {@code "11"} or greater. For example:</p> 151 152 <pre> 153 <manifest ... > 154 <uses-sdk android:minSdkVersion="4" 155 <b>android:targetSdkVersion="11"</b> /> 156 ... 157 </manifest> 158 </pre> 159 160 <p>In this example, the application requires a minimum version of API Level 4 (Android 1.6), but it 161 also targets API level 11 (Android 3.0). This way, when the application runs on Android 3.0 or 162 greater, the system applies the holographic theme to each activity, and thus, each activity includes 163 the action bar.</p> 164 165 <p>If you want to use {@link android.app.ActionBar} APIs, such as to add navigation modes and modify 166 action bar styles, you should set the <a 167 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> to {@code 168 "11"} or greater. If you want your app 169 to support older versions of Android, there are ways to use a limited set of {@link 170 android.app.ActionBar} APIs on devices that support API level 11 or higher, while still running 171 on older versions. See the sidebox for information about remaining backward-compatible.</p> 172 173 174 <h3 id="Removing">Removing the action bar</h3> 175 176 <p>If you don't want the action bar for a particular activity, set the activity theme to 177 {@link android.R.style#Theme_Holo_NoActionBar Theme.Holo.NoActionBar}. For example:</p> 178 179 <pre> 180 <activity android:theme="@android:style/Theme.Holo.NoActionBar"> 181 </pre> 182 183 <p>You can also hide the action bar at runtime by calling {@link android.app.ActionBar#hide}. For 184 example:</p> 185 186 <pre> 187 ActionBar actionBar = {@link android.app.Activity#getActionBar()}; 188 actionBar.hide(); 189 </pre> 190 191 <p>When the action bar hides, the system adjusts your activity layout to fill all the 192 screen space now available. You can bring the action bar back with {@link 193 android.app.ActionBar#show()}.</p> 194 195 <p>Beware that hiding and removing the action bar causes your activity to re-layout in order to 196 account for the space consumed by the action bar. If your activity regularly hides and shows the 197 action bar (such as in the Android Gallery app), you might want to use overlay mode. Overlay mode 198 draws the action bar on top of your activity layout rather than in its own area of the screen. This 199 way, your layout remains fixed when the action bar hides and re-appears. To enable overlay mode, 200 create a theme for your activity and set {@link android.R.attr#windowActionBarOverlay 201 android:windowActionBarOverlay} to {@code true}. For more information, see the section about <a 202 href="#Style">Styling the Action Bar</a>.</p> 203 204 <p class="note"><strong>Tip:</strong> If you have a custom activity theme in which you'd like to 205 remove the action bar, set the {@link android.R.styleable#Theme_windowActionBar 206 android:windowActionBar} style property to {@code false}. However, if you remove the action bar 207 using a theme, then the window will not allow the action bar at all, so you cannot add it 208 later—calling {@link android.app.Activity#getActionBar()} will return null.</p> 209 210 211 212 <h2 id="ActionItems">Adding Action Items</h2> 213 214 <p>Sometimes you might want to give users immediate access to an item from the <a 215 href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">options menu</a>. To do this, you can 216 declare that the menu item should appear in the action bar as an "action item." An action item can 217 include an icon and/or a text title. If a menu item does not appear as an action item, then the 218 system places it in the overflow menu. The overflow menu is revealed either by the device MENU 219 button (if provided by the device) or an additional button in the action bar (if the device does not 220 provide the MENU button).</p> 221 222 <div class="figure" style="width:359px"> 223 <img src="{@docRoot}images/ui/actionbar-item-withtext.png" height="57" alt="" /> 224 <p class="img-caption"><strong>Figure 2.</strong> Two action items with icon and text titles, and 225 the overflow menu button.</p> 226 </div> 227 228 <p>When the activity first starts, the system populates the action bar and overflow menu by calling 229 {@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()} for your activity. As 230 discussed in the <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a> developer guide, it's in 231 this callback method that you should inflate an XML <a 232 href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a> that defines the 233 menu items. For example:</p> 234 235 <pre> 236 @Override 237 public boolean onCreateOptionsMenu(Menu menu) { 238 MenuInflater inflater = getMenuInflater(); 239 inflater.inflate(R.menu.main_activity, menu); 240 return true; 241 } 242 </pre> 243 244 <p>In the XML file, you can request a menu item to appear as an action item by declaring {@code 245 android:showAsAction="ifRoom"} for the {@code <item>} element. This way, the menu item appears 246 in the action bar for quick access only <em>if there is room</em> available. If there's not 247 enough room, the item appears in the overflow menu.</p> 248 249 <p>If your menu item supplies both a title and an icon—with the {@code android:title} and 250 {@code android:icon} attributes—then the action item shows only the icon by default. If you 251 want to display the text title, add {@code "withText"} to the {@code android:showAsAction} 252 attribute. For example:</p> 253 254 <pre> 255 <?xml version="1.0" encoding="utf-8"?> 256 <menu xmlns:android="http://schemas.android.com/apk/res/android"> 257 <item android:id="@+id/menu_save" 258 android:icon="@drawable/ic_menu_save" 259 android:title="@string/menu_save" 260 <b>android:showAsAction="ifRoom|withText"</b> /> 261 </menu> 262 </pre> 263 264 <p class="note"><strong>Note:</strong> The {@code "withText"} value is a <em>hint</em> to the 265 action bar that the text title should appear. The action bar will show the title when possible, but 266 might not if an icon is available and the action bar is constrained for space.</p> 267 268 <p>When the user selects an action item, your activity receives a call to 269 {@link android.app.Activity#onOptionsItemSelected(MenuItem) 270 onOptionsItemSelected()}, passing the ID supplied by the {@code android:id} attribute—the same 271 callback received for all items in the options menu.</p> 272 273 <p>It's important that you always define {@code android:title} for each menu item—even if you 274 don't declare that the title appear with the action item—for three reasons:</p> 275 <ul> 276 <li>If there's not enough room in the action bar for the action item, the menu item appears 277 in the overflow menu and only the title appears.</li> 278 <li>Screen readers for sight-impaired users read the menu item's title.</li> 279 <li>If the action item appears with only the icon, a user can long-press the item to reveal a 280 tool-tip that displays the action item's title.</li> 281 </ul> 282 283 <p>The {@code android:icon} is always optional, but recommended. For icon design recommendations, 284 see the <a href="{@docRoot}guide/practices/ui_guidelines/icon_design_action_bar.html">Action Bar 285 Icon</a> design guidelines.</p> 286 287 <p class="note"><strong>Note:</strong> If you added the menu item from a fragment, via the {@link 288 android.app.Fragment} class's {@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu} 289 callback, then the system calls the respective {@link 290 android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} method for that 291 fragment when the user selects one of the fragment's items. However the activity gets a chance to 292 handle the event first, so the system calls {@link 293 android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} on the activity before 294 calling the same callback for the fragment.</p> 295 296 <p>You can also declare an item to <em>"always"</em> appear as an action item, instead of being 297 placed in the overflow menu when space is limited. In most cases, you <strong>should not</strong> 298 force an item to appear in the action bar by using the {@code "always"} value. However, you might 299 need an item to always appear when it provides an <a href="#ActionView">action view</a> that does 300 not offer a default action for the overflow menu. Beware that too 301 many action items can create a cluttered UI and cause layout problems on devices with a narrow 302 screen. It's best to instead use {@code "ifRoom"} to request that an item appear in the action 303 bar, but allow the system to move it into the overflow menu when there's not enough room.</p> 304 305 <p>For more information about creating the options menu that defines your action items, see the <a 306 href="{@docRoot}guide/topics/ui/menus.html#options-menu">Menus</a> developer guide.</p> 307 308 309 310 <h3 id="ChoosingActionItems">Choosing your action items</h3> 311 312 <div class="sidebox-wrapper"> 313 <div class="sidebox"> 314 <h4>Menu items vs. other app controls</h4> 315 <p>As a general rule, all items in the <a 316 href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">options menu</a> (let alone action items) 317 should have a global impact on the app, rather than affect only a small portion of the interface. 318 For example, if you have a multi-pane layout and one pane shows a video while another lists all 319 videos, the video player controls should appear within the pane containing the video (not in the 320 action bar), while the action bar might provide action items to share the video or save the video to 321 a favorites list.</p> 322 <p>So, even before deciding whether a menu item should appear as an action item, be sure that 323 the item has a global scope for the current activity. If it doesn't, then you should place it 324 as a button in the appropriate context of the activity layout.</p> 325 </div> 326 </div> 327 328 <p>You should carefully choose which items from your options menu should appear as action items by 329 assessing a few key traits. In general, each action item should be <em>at least one</em> 330 of the following:</p> 331 332 <ol> 333 <li><strong>Frequently used</strong>: It's an action that your users need seven out of ten visits 334 or they use it several times in a row. 335 <p>Example frequent actions: "New message" in the Messaging app and 336 "Search" in Android Market.</p> 337 </li> 338 339 <li><strong>Important</strong>: It's an action that you need users to easily discover or, if it's 340 not frequently used, it's important that it be effortless to perform in the few cases that users do 341 need it. 342 <p>Example important actions: "Add network" in Wi-Fi settings and "Switch to camera" in the 343 Gallery app.</p> 344 </li> 345 346 <li><strong>Typical</strong>: It's an action that is typically provided in the action bar in 347 similar apps, so your users expect to find it in yours. 348 <p>Example typical actions: "Refresh" in an email or social app, and "New contact" in the 349 People app.</p> 350 </ol> 351 352 <p>If you believe that more than four of your menu items can be justified as action items, then you 353 should carefully consider their relative level of importance and try to set no more than four as 354 action items (and do so using the {@code "ifRoom"} value to allow the system to put some back in the 355 overflow menu when space is limited on smaller screens). Even if space is available on a wide 356 screen, you should not create a long stream of action items that clutter the UI and appear like a 357 desktop toolbar, so keep the number of action items to a minimum.</p> 358 359 <p>Additionally, the following actions should never appear as action items: Settings, Help, 360 Feedback, or similar. Always keep them in the overflow menu.</p> 361 362 <p class="note"><strong>Note:</strong> Remember that not all devices provide a dedicated hardware 363 button for Search, so if it's an important feature in your app, it should always appear as an 364 action item (and usually as the first item, especially if you offer it with an <a 365 href="#ActionView">action view</a>).</p> 366 367 368 369 <h3 id="SplitBar">Using split action bar</h3> 370 371 <p>When your application is running on Android 4.0 (API level 14) and higher, there's an extra mode 372 available for the action bar called "split action bar." When you enable split action bar, a separate 373 bar appears at the bottom of the screen to display all action items when the activity is running on 374 a narrow screen (such as a portrait-oriented handset). Splitting the action bar to separate 375 the action items ensures that a reasonable amount of space is available to display all your action 376 items on a narrow screen, while leaving room for navigation and title elements at the top.</p> 377 378 <p>To enable split action bar, simply add {@code uiOptions="splitActionBarWhenNarrow"} to your 379 <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> or 380 <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a> 381 manifest element.</p> 382 383 <p>Be aware that Android adjusts the action bar's appearance in a variety of ways, based on the 384 current screen size. Using split action bar is just one option that you can enable to allow the 385 action bar to further optimize the user experience for different screen sizes. In doing so, you 386 may also allow the action bar to collapse navigation tabs into the main action bar. That is, if you 387 use <a href="#Tabs">navigation tabs</a> in your action bar, once the action items are 388 separated on a narrow screen, the navigation tabs may be able to fit into the main action bar rather 389 than be separated into the "stacked action bar." Specifically, if you've disabled the action bar 390 icon and title (with {@link android.app.ActionBar#setDisplayShowHomeEnabled 391 setDisplayShowHomeEnabled(false)} and {@link android.app.ActionBar#setDisplayShowTitleEnabled 392 setDisplayShowTitleEnabled(false)}), then the navigation tabs collapse into the main action bar, as 393 shown by the second device in figure 3.</p> 394 395 <img src="{@docRoot}images/practices/actionbar-phone-splitaction.png" alt=""/> 396 <p class="img-caption"><strong>Figure 3.</strong> Mock-ups of split action bar with navigation tabs 397 on the left; with the app icon and title disabled on the right.</p> 398 399 <p class="note"><strong>Note:</strong> Although the {@link android.R.attr#uiOptions 400 android:uiOptions} attribute was added in Android 4.0 (API level 14), you can safely include it in 401 your application even if your <a 402 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> is set to 403 a value lower than {@code "14"} to remain compatible with older versions of Android. When running on 404 older versions, the system simply ignores the XML attribute because it doesn't understand it. The 405 only condition to including it in your manifest is that you must compile your application against a 406 platform version that supports API level 14 or higher. Just be sure that you don't openly use other 407 APIs in your application code that aren't supported by the version declared by your <a 408 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> 409 attribute—only XML attributes are safely ignored by older platforms.</p> 410 411 412 413 414 <h2 id="Home">Using the App Icon for Navigation</h2> 415 416 417 <div class="sidebox-wrapper"> 418 <div class="sidebox"> 419 <h2>Using a logo instead of icon</h2> 420 <p>By default, the system uses your application icon in the action bar, as specified by the <a 421 href="{@docRoot}guide/topics/manifest/application-element.html#icon">{@code android:icon}</a> 422 attribute in the <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code 423 <application>}</a> or <a 424 href="{@docRoot}guide/topics/manifest/activity-element.html">{@code 425 <activity>}</a> element. However, if you also specify the <a 426 href="{@docRoot}guide/topics/manifest/application-element.html#logo">{@code android:logo}</a> 427 attribute, then the action bar uses the logo image instead of the icon.</p> 428 <p>A logo should usually be wider than the icon, but should not include unnecessary text. You 429 should generally use a logo only when it represents your brand in a traditional format that users 430 recognize. A good example is the YouTube app's logo—the logo represents the expected user 431 brand, whereas the app's icon is a modified version that conforms to the square requirement.</p> 432 </div> 433 </div> 434 435 436 <p>By default, your application icon appears in the action bar on the left side. If you'd like, 437 you can enable the icon to behave as an action item. In response to user action on the icon, your 438 application should do one of two things:</p> 439 440 <ul> 441 <li>Go to the application "home" activity, or</li> 442 <li>Navigate "up" the application's structural hierarchy</li> 443 </ul> 444 445 <p>When the user touches the icon, the system calls your activity's {@link 446 android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} method with the {@code 447 android.R.id.home} ID. In response, you should either start the home activity or 448 take the user one step up in your application's structural hierarchy.</p> 449 450 <p>If you respond to the application icon by returning to the home activity, you should include 451 the {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag in the {@link 452 android.content.Intent}. With this flag, if the activity you're starting already exists in the 453 current task, then all activities on top of it are destroyed and it is brought to the front. 454 Adding this flag is often important because going "home" is an action that's equivalent to "going 455 back" and you should usually not create a new instance of the home activity. Otherwise, you 456 might end up with a long stack of activities in the current task with multiple instances of the 457 home activity.</p> 458 459 <p>For example, here's an implementation of {@link android.app.Activity#onOptionsItemSelected 460 onOptionsItemSelected()} that returns to the application's "home" activity:</p> 461 462 <pre> 463 @Override 464 public boolean onOptionsItemSelected(MenuItem item) { 465 switch (item.getItemId()) { 466 case android.R.id.home: 467 // app icon in action bar clicked; go home 468 Intent intent = new Intent(this, HomeActivity.class); 469 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 470 startActivity(intent); 471 return true; 472 default: 473 return super.onOptionsItemSelected(item); 474 } 475 } 476 </pre> 477 478 <p>In case the user can enter the current activity from another application, you might also want to 479 add the {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag. This flag ensures that, when the 480 user navigates either "home" or "up", the new activity is <strong>not</strong> added to the current 481 task, but instead started in a task that belongs to your application. For example, if the user 482 starts an activity in your application through an intent invoked by another application, then 483 selects the action bar icon to navigate home or up, the {@link 484 android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag starts the activity in a task that belongs to 485 your application (not the current task). The system either starts a new task with your new activity 486 as the root activity or, if an existing task exists in the background with an instance of that 487 activity, then that task is brought forward and the target activity receives {@link 488 android.app.Activity#onNewIntent onNewIntent()}. So if your activity accepts intents from other 489 applications (it declares any generic intent filters), you should usually add the {@link 490 android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag to the intent:</p> 491 492 <pre> 493 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 494 </pre> 495 496 <p>For more information about these flags and other back stack behaviors, read the <a 497 href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a> 498 developer guide.</p> 499 500 <p class="note"><strong>Note:</strong> If you're using the icon to navigate to the home 501 activity, beware that beginning with Android 4.0 (API level 14), you must explicitly enable the 502 icon as an action item by calling {@link android.app.ActionBar#setHomeButtonEnabled 503 setHomeButtonEnabled(true)} (in previous versions, the icon was enabled as an action item by 504 default).</p> 505 506 507 508 <h3 id="Up">Navigating up</h3> 509 510 <div class="figure" style="width:230px;margin-top:-1em"> 511 <img src="{@docRoot}images/ui/actionbar-logo.png" alt="" /> 512 <p class="img-caption"><strong>Figure 4.</strong> The Email app's standard icon 513 (left) and the "navigate up" icon (right). The system automatically adds the "up" indicator.</p> 514 </div> 515 516 <p>As a supplement to traditional "back" navigation—which takes the user to the previous 517 screen in the task history—you can enable the action bar icon to offer "up" 518 navigation, which should take the user one step up in your application's structural hierarchy. For 519 instance, if the current screen is somewhere deep in the hierarchy of the application, touching the 520 app icon should navigate upward one level, to the parent of the current screen.</p> 521 522 <p>For example, figure 5 illustrates how the BACK button behaves when the user navigates from one 523 application to an activity belonging to a different application (specifically, when composing an 524 email to a person selected from the People app).</p> 525 526 <img src="{@docRoot}images/ui/actionbar-navigate-back.png" alt="" /> 527 <p class="img-caption"><strong>Figure 5.</strong> The BACK button behavior 528 after entering the Email app from the People (or Contacts) app.</p> 529 530 <p>However, if the user wants to stay within the email application after composing the email, 531 up navigation allows the user to navigate upward in the email application, rather than go back 532 to the previous activity. Figure 6 illustrates this scenario, in which the user again comes into 533 the email application, but presses the action bar icon to navigate up, rather than back.</p> 534 535 <img src="{@docRoot}images/ui/actionbar-navigate-up.png" alt="" /> 536 <p class="img-caption"><strong>Figure 6.</strong> Example behavior for UP navigation after 537 entering the Email app from the People app.</p> 538 539 <p>To enable the icon for up navigation (which displays the "up" indicator next to the icon), call 540 {@link android.app.ActionBar#setDisplayHomeAsUpEnabled setDisplayHomeAsUpEnabled(true)} on your 541 {@link android.app.ActionBar}:</p> 542 543 <pre> 544 protected void onCreate(Bundle savedInstanceState) { 545 super.onCreate(savedInstanceState); 546 547 setContentView(R.layout.main); 548 ActionBar actionBar = getActionBar(); 549 actionBar.setDisplayHomeAsUpEnabled(true); 550 ... 551 } 552 </pre> 553 554 <p>When the user touches the icon, the system calls your activity's {@link 555 android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} method with the {@code 556 android.R.id.home} ID, as shown in the above section about <a href="#Home">Using the App Icon 557 for Navigation</a>.</p> 558 559 <p>Remember to use the {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag in the {@link 560 android.content.Intent}, so that you don't create a new instance of the parent activity if one 561 already exists. For instance, if you don't use the {@link 562 android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag, then after navigating up, the BACK button will 563 actually take the user "forward", with respect to the application structure, which would be 564 strange.</p> 565 566 <p class="note"><strong>Note:</strong> If there are many paths that the user could have taken to 567 reach the current activity within your application, the up icon should navigate backward along the 568 path the user actually followed to get to the current activity.</p> 569 570 571 572 573 <h2 id="ActionView">Adding an Action View</h2> 574 575 <div class="figure" style="width:300px;margin-top:-1em"> 576 <img src="/images/ui/actionbar-searchview.png" alt="" /> 577 <p class="img-caption"><strong>Figure 7.</strong> An action bar with a collapsed action 578 view for Search (top), then expanded action view with the <code><a 579 href="/reference/android/widget/SearchView.html">SearchView</a></code> widget (bottom).</p> 580 </div> 581 582 583 <p>An action view is a widget that appears in the action bar as a substitute for an action item's 584 button. For example, if you have an item in the options menu for "Search," you can add an action 585 view that replaces the button with a {@link android.widget.SearchView} widget, as shown in figure 586 7.</p> 587 588 <p>To declare an action view for an item in your <a 589 href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>, use either the {@code 590 android:actionLayout} or {@code android:actionViewClass} attribute to specify either a layout 591 resource or widget class to use, respectively. For example:</p> 592 593 <pre> 594 <?xml version="1.0" encoding="utf-8"?> 595 <menu xmlns:android="http://schemas.android.com/apk/res/android"> 596 <item android:id="@+id/menu_search" 597 android:title="@string/menu_search" 598 android:icon="@drawable/ic_menu_search" 599 android:showAsAction="ifRoom|collapseActionView" 600 <b>android:actionViewClass="android.widget.SearchView"</b> /> 601 </menu> 602 </pre> 603 604 <p>Notice that the {@code android:showAsAction} attribute also includes {@code 605 "collapseActionView"}. This is optional and declares that the action view should be collapsed into a 606 button. When the user selects the button, the action view expands. Otherwise, the action view is 607 visible by default and might consume valuable action bar space even when the user is not using it. 608 For more information, see the next section about <a href="#ActionViewCollapsing">Handling 609 collapsible action views</a>.</p> 610 611 <p>If you need to add some event hooks to your action view, you can do so during the {@link 612 android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()} callback. You can acquire elements 613 in an action view by calling {@link android.view.Menu#findItem findItem()} with the ID of the menu 614 item, then call {@link android.view.MenuItem#getActionView}. For 615 example, the search widget from the above sample is acquired like this:</p> 616 617 <pre> 618 @Override 619 public boolean onCreateOptionsMenu(Menu menu) { 620 getMenuInflater().inflate(R.menu.options, menu); 621 SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView(); 622 // Configure the search info and add any event listeners 623 ... 624 return super.onCreateOptionsMenu(menu); 625 } 626 </pre> 627 628 <p>For more information about using the search widget, see <a 629 href="{@docRoot}guide/topics/search/search-dialog.html">Creating a Search Interface</a>.</p> 630 631 632 <h3 id="ActionViewCollapsing">Handling collapsible action views</h3> 633 634 <div class="sidebox-wrapper"> 635 <div class="sidebox"> 636 <h3>Supporting Android 3.0 with an action view</h3> 637 <p>The {@code "collapseActionView"} option was added with Android 4.0 (API level 14). However, if 638 your application supports older versions, you should 639 still declare {@code "collapseActionView"} in order to better support smaller screens. 640 Devices running Android 4.0 and higher will show the action view collapsed, while older versions 641 work as designed otherwise.</p> 642 <p>Adding this value requires that you set your build target to Android 4.0 or higher in order to 643 compile. Older versions of Android ignore the {@code "collapseActionView"} value because they don't 644 understand it. Just be sure not to use other APIs in your source code that are not supported in the 645 version declared by your <a href="{@docRoot}guide/topics/manifest/uses-sdk-elementl.html#min">{@code 646 minSdkVersion}</a>, unless you add the appropriate version check at runtime.</p> 647 </div> 648 </div> 649 650 651 <p>Action views allow you to provide fast access to rich actions without changing activities or 652 fragments, or replacing the action bar. However, it might not be appropriate to make an action view 653 visible by default. To preserve the action bar space (especially when running on smaller screens), 654 you can collapse your action view into an action item button. When the user selects the 655 button, the action view appears in the action bar. When collapsed, the system might place the item 656 into the overflow menu if you've defined {@code android:showAsAction} with {@code "ifRoom"}, but the 657 action view still appears in the action bar when the user selects the item. You can make your action 658 view collapsible by adding {@code "collapseActionView"} to the {@code android:showAsAction} 659 attribute, as shown in the XML above.</p> 660 661 <p>Because the system will expand the action view when the user selects the item, so you 662 <em>do not</em> need to respond to the item in the {@link 663 android.app.Activity#onOptionsItemSelected onOptionsItemSelected} callback. The system still calls 664 {@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} when the user selects it, 665 but the system will always expand the action view unless you return {@code true} (indicating 666 you've handled the event instead).</p> 667 668 <p>The system also collapses your action view when the user selects the "up" icon in the action 669 bar or presses the BACK button.</p> 670 671 <p>If necessary, you can expand or collapse the action view in your own code by calling {@link 672 android.view.MenuItem#expandActionView()} and {@link android.view.MenuItem#collapseActionView()} on 673 the {@link android.view.MenuItem}.</p> 674 675 <p class="note"><strong>Note:</strong> Although collapsing your action view is optional, we 676 recommend that you always collapse your action view if it includes {@link 677 android.widget.SearchView}. Also be aware that some devices provide a dedicated SEARCH button and 678 you should expand your search action view if the user presses the SEARCH button. Simply override 679 your activity's {@link android.app.Activity#onKeyUp onKeyUp()} callback method, listen for the 680 {@link android.view.KeyEvent#KEYCODE_SEARCH} event, then call {@link 681 android.view.MenuItem#expandActionView()}.</p> 682 683 <p>If you need to update your activity based on the visibility of your action view, you can receive 684 callbacks when it's expanded and collapsed by defining an {@link 685 android.view.MenuItem.OnActionExpandListener OnActionExpandListener} and registering it with {@link 686 android.view.MenuItem#setOnActionExpandListener setOnActionExpandListener()}. For example:</p> 687 688 <pre> 689 @Override 690 public boolean onCreateOptionsMenu(Menu menu) { 691 getMenuInflater().inflate(R.menu.options, menu); 692 MenuItem menuItem = menu.findItem(R.id.actionItem); 693 ... 694 695 menuItem.setOnActionExpandListener(new OnActionExpandListener() { 696 @Override 697 public boolean onMenuItemActionCollapse(MenuItem item) { 698 // Do something when collapsed 699 return true; // Return true to collapse action view 700 } 701 702 @Override 703 public boolean onMenuItemActionExpand(MenuItem item) { 704 // Do something when expanded 705 return true; // Return true to expand action view 706 } 707 }); 708 } 709 </pre> 710 711 712 713 714 <h2 id="ActionProvider">Adding an Action Provider</h2> 715 716 <div class="figure" style="width:200px"> 717 <img src="{@docRoot}images/ui/actionbar-shareaction.png" alt="" /> 718 <p class="img-caption"><strong>Figure 8.</strong> Screenshot from the Gallery app, with the 719 {@link android.widget.ShareActionProvider} submenu expanded to show share targets.</p> 720 </div> 721 722 <p>Similar to an <a href="#ActionView">action view</a>, an action provider (defined by the {@link 723 android.view.ActionProvider} class) replaces an action item with a customized layout, but it also 724 takes control of all the item's behaviors. When you declare an action provider for a menu 725 item in the action bar, it not only controls the appearance of the item in the action bar with a 726 custom layout, but also handles the default event for the menu item when it appears in the overflow 727 menu. It can also provide a submenu from either the action bar or the overflow menu.</p> 728 729 <p>For example, the {@link android.widget.ShareActionProvider} is an extension of {@link 730 android.view.ActionProvider} that facilitates a share" action by showing a list of available share 731 targets from the action bar. Instead of using a 732 traditional action item that invokes the {@link android.content.Intent#ACTION_SEND} intent, you can 733 declare an instance of {@link android.widget.ShareActionProvider} to handle an action item. This 734 action provider presents an action view with a drop-down list of applications that handle 735 the {@link android.content.Intent#ACTION_SEND} intent, even when the menu item appears in the 736 overflow menu. Hence, when you use an action provider such as this one, you don't 737 have to handle user events on the menu item.</p> 738 739 <p>To declare an action provider for an action item, define the {@code android:actionProviderClass} 740 attribute for the appropriate the {@code <item>} element in your <a 741 href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>, using the 742 fully-qualified class name of the action provider. For example:</p> 743 744 <pre> 745 <?xml version="1.0" encoding="utf-8"?> 746 <menu xmlns:android="http://schemas.android.com/apk/res/android"> 747 <item android:id="@+id/menu_share" 748 android:title="@string/share" 749 android:showAsAction="ifRoom" 750 <strong>android:actionProviderClass="android.widget.ShareActionProvider"</strong> /> 751 ... 752 </menu> 753 </pre> 754 755 <p>In this example, the {@link android.widget.ShareActionProvider} is used as the action provider. 756 At this point, the action provider officially takes control of the menu item and handles both 757 its appearance and behavior in the action bar and its behavior in the overflow menu. You must 758 still provide a text title for the item to be used in the overflow menu.</p> 759 760 <p>Although the action provider can perform the default action for the menu item when it appears in 761 the overflow menu, your activity (or fragment) can override that behavior by 762 also handling the click event from the {@link android.app.Activity#onOptionsItemSelected 763 onOptionsItemSelected()} callback method. If you do not handle the event in that callback, then 764 the action provider receives the {@link android.view.ActionProvider#onPerformDefaultAction()} 765 callback to handle the event. However, if the action provider provides a submenu, then your 766 activity will not receive the {@link android.app.Activity#onOptionsItemSelected 767 onOptionsItemSelected()} callback, because the submenu is shown instead of invoking the default 768 menu item behavior when selected.</p> 769 770 771 772 <h3 id="ShareActionProvider">Using the ShareActionProvider</h3> 773 774 <p>If you want to provide a "share" action in your action bar by leveraging other applications 775 installed on the device (for example, to share a photo using a messaging or social app), then using 776 {@link android.widget.ShareActionProvider} is an effective way to do so, rather than adding an 777 action item that invokes the {@link android.content.Intent#ACTION_SEND} intent. When 778 you use {@link android.widget.ShareActionProvider} for an action item, it presents an action view 779 with a drop-down list of applications that handle the {@link android.content.Intent#ACTION_SEND} 780 intent (as shown in figure 8).</p> 781 782 <p>All the logic for creating the submenu, populating it with share targets, and handling click 783 events (including when the item appears in the overflow menu) is implemented by the {@link 784 android.widget.ShareActionProvider}—the only code you need to write is to declare the action 785 provider for the menu item and specify the share intent.</p> 786 787 <p>By default, the {@link android.widget.ShareActionProvider} retains a ranking for each 788 share target based on how often the user selects each one. The share targets used more frequently 789 appear at the top of the drop-down list and the target used most often appears directly in the 790 action bar as the default share target. By default, the ranking information is 791 saved in a private file with a name specified by {@link 792 android.widget.ShareActionProvider#DEFAULT_SHARE_HISTORY_FILE_NAME}. If you use the {@link 793 android.widget.ShareActionProvider} or an extension of it for only one type of action, then you 794 should continue to use this default history file and there's nothing you need to do. However, if you 795 use {@link android.widget.ShareActionProvider} or an extension of it for multiple actions with 796 semantically different meanings, then each {@link android.widget.ShareActionProvider} should specify 797 its own history file in order to maintain its own history. To specify a 798 different history file for the {@link android.widget.ShareActionProvider}, call {@link 799 android.widget.ShareActionProvider#setShareHistoryFileName setShareHistoryFileName()} and provide 800 an XML file name (for example, {@code "custom_share_history.xml"}).</p> 801 802 <p class="note"><strong>Note:</strong> Although the {@link android.widget.ShareActionProvider} ranks 803 share targets based on frequency of use, the behavior is extensible and extensions of {@link 804 android.widget.ShareActionProvider} can perform different behaviors and ranking based on the history 805 file (if appropriate).</p> 806 807 <p>To add {@link android.widget.ShareActionProvider}, simply define the {@code 808 android:actionProviderClass} attribute with {@code "android.widget.ShareActionProvider"}, as shown 809 in the XML example above. The only thing left to do is define 810 the {@link android.content.Intent} you want to use for sharing. To do so, you must call {@link 811 android.view.MenuItem#getActionProvider} to retrieve the {@link android.widget.ShareActionProvider} 812 that's associated with a {@link android.view.MenuItem}, then call {@link 813 android.widget.ShareActionProvider#setShareIntent setShareIntent()}.</p> 814 815 <p>If the format for the share intent depends on the selected item or other variables that change 816 during the activity lifecycle, you should save the {@link android.widget.ShareActionProvider} in a 817 member field and update it by calling {@link android.widget.ShareActionProvider#setShareIntent 818 setShareIntent()} as necessary. For example:</p> 819 820 <pre> 821 private ShareActionProvider mShareActionProvider; 822 ... 823 824 @Override 825 public boolean onCreateOptionsMenu(Menu menu) { 826 mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share).getActionProvider(); 827 828 // If you use more than one ShareActionProvider, each for a different action, 829 // use the following line to specify a unique history file for each one. 830 // mShareActionProvider.setShareHistoryFileName("custom_share_history.xml"); 831 832 // Set the default share intent 833 mShareActionProvider.setShareIntent(getDefaultShareIntent()); 834 835 return true; 836 } 837 // When you need to update the share intent somewhere else in the app, call 838 // mShareActionProvider.{@link android.widget.ShareActionProvider#setShareIntent setShareIntent()} 839 </pre> 840 841 <p>The {@link android.widget.ShareActionProvider} now handles all user interaction with the item and 842 you <em>do not</em> need to handle click events from the {@link 843 android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} callback method.</p> 844 845 <p>For a sample using the share action provider, see 846 <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ActionBarActionProviderActivity.html" 847 >ActionBarActionProviderActivity</a>. 848 849 850 851 <h3 id="CreatingActionProvider">Creating a custom action provider</h3> 852 853 <p>When you want to create an action view that has dynamic behaviors and a default action in the 854 overflow menu, extending {@link android.view.ActionProvider} to define those behaviors is a good 855 solution. Creating your own action provider offers you an organized and reusable component, rather 856 than handling the various action item transformations and behaviors in your fragment or activity 857 code. As shown in the previous section, Android provides one implementation of {@link 858 android.view.ActionProvider} for share actions: the {@link android.widget.ShareActionProvider}.</p> 859 860 <p>To create your own, simply extend the {@link android.view.ActionProvider} class and implement 861 its callback methods as appropriate. Most importantly, you should implement the following:</p> 862 863 <dl> 864 <dt>{@link android.view.ActionProvider#ActionProvider ActionProvider()}</dt> 865 <dd>This constructor passes you the application {@link android.content.Context}, which you 866 should save in a member field to use in the other callback methods.</dd> 867 868 <dt>{@link android.view.ActionProvider#onCreateActionView()}</dt> 869 <dd>This is where you define the action view for the item. Use the {@link 870 android.content.Context} acquired from the constructor to instantiate a {@link 871 android.view.LayoutInflater} and inflate your action view layout from an XML resource, then hook 872 up event listeners. For example: 873 <pre> 874 public View onCreateActionView() { 875 // Inflate the action view to be shown on the action bar. 876 LayoutInflater layoutInflater = LayoutInflater.from(mContext); 877 View view = layoutInflater.inflate(R.layout.action_provider, null); 878 ImageButton button = (ImageButton) view.findViewById(R.id.button); 879 button.setOnClickListener(new View.OnClickListener() { 880 @Override 881 public void onClick(View v) { 882 // Do something... 883 } 884 }); 885 return view; 886 } 887 </pre> 888 </dd> 889 890 <dt>{@link android.view.ActionProvider#onPerformDefaultAction()}</dt> 891 <dd>The system calls this when the menu item is selected from the overflow menu and the 892 action provider should perform a default action for the menu item. 893 <p>However, if your action provider provides a submenu, through the {@link 894 android.view.ActionProvider#onPrepareSubMenu onPrepareSubMenu()} callback, then the submenu 895 appears even when the menu item is in the overflow menu. Thus, {@link 896 android.view.ActionProvider#onPerformDefaultAction()} is never called when there is a 897 submenu.</p> 898 <p class="note"><strong>Note:</strong> An activity or a fragment that implements {@link 899 android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} can override the action 900 provider's default behavior by handling the item-selected event (and returning true), in which 901 case, the system does not call {@link android.view.ActionProvider#onPerformDefaultAction()}.</p> 902 </dd> 903 </dl> 904 905 <p>For an example extension of {@link android.view.ActionProvider}, see <a 906 href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ActionBarSettingsActionProviderActivity.html" 907 >ActionBarSettingsActionProviderActivity</a>.</p> 908 909 910 911 912 <h2 id="Tabs">Adding Navigation Tabs</h2> 913 914 915 <div class="figure" style="width:450px"> 916 <img src="{@docRoot}images/ui/actionbar.png" alt="" /> 917 <p class="img-caption"><strong>Figure 9.</strong> Screenshot of action bar tabs from the <a 918 href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a> app.</p> 919 </div> 920 921 <div class="figure" style="width:250px"> 922 <img src="{@docRoot}images/ui/actionbar-stacked.png" alt="" /> 923 <p class="img-caption"><strong>Figure 10.</strong> Screenshot of tabs in the stacked action 924 bar on a narrow screen.</p> 925 </div> 926 927 <p>When you want to provide navigation tabs in an activity, using the action bar's 928 tabs is a great option (instead of using {@link android.widget.TabWidget}), because the 929 system adapts the action bar tabs for different screen sizes—placing them in the main action 930 bar when the screen is sufficiently wide, or in a separate bar (known as the "stacked action bar") 931 when the screen is too narrow, as shown in figures 9 and 10.</p> 932 933 <p>To switch between fragments using the tabs, you must perform a fragment 934 transaction each time a tab is selected. If you're not familiar with how to change fragments 935 using {@link android.app.FragmentTransaction}, first read the <a 936 href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p> 937 938 <p>To get started, your layout must include a {@link android.view.ViewGroup} in which you place each 939 {@link android.app.Fragment} associated with a tab. Be sure the {@link android.view.ViewGroup} has a 940 resource ID so you can reference it from your tab-swapping code. Alternatively, if the tab content 941 will fill the activity layout (excluding the action bar), then your activity doesn't need a layout 942 at all (you don't even need to call {@link android.app.Activity#setContentView 943 setContentView()}). Instead, you can place each fragment in the default root {@link 944 android.view.ViewGroup}, which you can refer to with the {@code android.R.id.content} ID (you can 945 see this ID used in the sample code below, during fragment transactions).</p> 946 947 <p>Once you determine where the fragments appear in the layout, the basic procedure to add tabs 948 is:</p> 949 <ol> 950 <li>Implement the {@link android.app.ActionBar.TabListener} interface. Callbacks in this 951 interface respond to user events on the tabs so you can swap fragments.</li> 952 <li>For each tab you want to add, instantiate an {@link android.app.ActionBar.Tab} and set the 953 {@link android.app.ActionBar.TabListener} by calling {@link android.app.ActionBar.Tab#setTabListener 954 setTabListener()}. Also set the tab's title and/or icon with {@link 955 android.app.ActionBar.Tab#setText setText()} and/or {@link android.app.ActionBar.Tab#setIcon 956 setIcon()}.</li> 957 <li>Add each tab to the action bar by calling {@link android.app.ActionBar#addTab addTab()}.</li> 958 </ol> 959 960 <p>When looking at the {@link android.app.ActionBar.TabListener} interface, notice that the 961 callback methods provide only the {@link android.app.ActionBar.Tab} that was selected and a {@link 962 android.app.FragmentTransaction} for you to perform fragment transactions—it doesn't say 963 anything about what fragment you should swap in or out. Thus, you must define your own association 964 between each {@link android.app.ActionBar.Tab} and the appropriate {@link android.app.Fragment} that 965 it represents (in order to perform the appropriate fragment transaction). There are several ways you 966 can define the association, depending on your design. In the example below, the {@link 967 android.app.ActionBar.TabListener} implementation provides a constructor such that each new tab uses 968 its own instance of the listener. Each instance of the listener defines several fields that are 969 necessary to later perform a transaction on the appropriate fragment.</p> 970 971 <p>For example, here's how you might implement the {@link android.app.ActionBar.TabListener} 972 such that each tab uses its own instance of the listener:</p> 973 <pre> 974 public static class TabListener<T extends Fragment> implements ActionBar.TabListener { 975 private Fragment mFragment; 976 private final Activity mActivity; 977 private final String mTag; 978 private final Class<T> mClass; 979 980 /** Constructor used each time a new tab is created. 981 * @param activity The host Activity, used to instantiate the fragment 982 * @param tag The identifier tag for the fragment 983 * @param clz The fragment's Class, used to instantiate the fragment 984 */ 985 public TabListener(Activity activity, String tag, Class<T> clz) { 986 mActivity = activity; 987 mTag = tag; 988 mClass = clz; 989 } 990 991 /* The following are each of the {@link android.app.ActionBar.TabListener} callbacks */ 992 993 public void onTabSelected(Tab tab, FragmentTransaction ft) { 994 // Check if the fragment is already initialized 995 if (mFragment == null) { 996 // If not, instantiate and add it to the activity 997 mFragment = Fragment.instantiate(mActivity, mClass.getName()); 998 ft.add(android.R.id.content, mFragment, mTag); 999 } else { 1000 // If it exists, simply attach it in order to show it 1001 ft.attach(mFragment); 1002 } 1003 } 1004 1005 public void onTabUnselected(Tab tab, FragmentTransaction ft) { 1006 if (mFragment != null) { 1007 // Detach the fragment, because another one is being attached 1008 ft.detach(mFragment); 1009 } 1010 } 1011 1012 public void onTabReselected(Tab tab, FragmentTransaction ft) { 1013 // User selected the already selected tab. Usually do nothing. 1014 } 1015 } 1016 </pre> 1017 1018 <p class="caution"><strong>Caution:</strong> You <strong>must not</strong> call {@link 1019 android.app.FragmentTransaction#commit} for the fragment transaction in each of these 1020 callbacks—the system calls it for you and it may throw an exception if you call it yourself. 1021 You also <strong>cannot</strong> add these fragment transactions to the back stack.</p> 1022 1023 <p>In this example, the listener simply attaches ({@link android.app.FragmentTransaction#attach 1024 attach()}) a fragment to the activity layout—or if not instantiated, creates the fragment and 1025 adds ({@link android.app.FragmentTransaction#add add()}) it to the layout (as a child of the {@code 1026 android.R.id.content} view group)—when the respective tab is selected, and detaches ({@link 1027 android.app.FragmentTransaction#detach detach()}) it when the tab is unselected.</p> 1028 1029 <p>The {@link android.app.ActionBar.TabListener} implementation is the bulk of the work. All that 1030 remains is to create each {@link android.app.ActionBar.Tab} and add it to the {@link 1031 android.app.ActionBar}. Additionally, you must call {@link 1032 android.app.ActionBar#setNavigationMode(int) setNavigationMode(NAVIGATION_MODE_TABS)} to make the 1033 tabs visible. You might also want to disable the activity title by calling {@link 1034 android.app.ActionBar#setDisplayShowTitleEnabled setDisplayShowTitleEnabled(false)} if the tab 1035 titles actually indicate the current view.</p> 1036 1037 <p>For example, the following code adds two tabs using the listener defined above:</p> 1038 1039 <pre> 1040 @Override 1041 protected void onCreate(Bundle savedInstanceState) { 1042 super.onCreate(savedInstanceState); 1043 // Notice that setContentView() is not used, because we use the root 1044 // android.R.id.content as the container for each fragment 1045 1046 // setup action bar for tabs 1047 ActionBar actionBar = getActionBar(); 1048 actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 1049 actionBar.setDisplayShowTitleEnabled(false); 1050 1051 Tab tab = actionBar.newTab() 1052 .setText(R.string.artist) 1053 .setTabListener(new TabListener<ArtistFragment>( 1054 this, "artist", ArtistFragment.class)); 1055 actionBar.addTab(tab); 1056 1057 tab = actionBar.newTab() 1058 .setText(R.string.album) 1059 .setTabListener(new TabListener<AlbumFragment>( 1060 this, "album", AlbumFragment.class)); 1061 actionBar.addTab(tab); 1062 } 1063 </pre> 1064 1065 <p class="note"><strong>Note:</strong> The above implementation for {@link 1066 android.app.ActionBar.TabListener} is one of several possible techniques. You can see more of 1067 this style in the <a 1068 href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.html" 1069 >API Demos</a> app.</p> 1070 1071 1072 <p>If your activity stops, you should retain the currently selected tab with the <a 1073 href="{@docRoot}guide/topics/fundamentals/activities.html#SavingActivityState">saved instance 1074 state</a> so you can open the appropriate tab when the user returns. When it's time to save the 1075 state, you can query the currently selected tab with {@link 1076 android.app.ActionBar#getSelectedNavigationIndex()}. This returns the index position of the selected 1077 tab.</p> 1078 1079 <p class="caution"><strong>Caution:</strong> It's important that you save the state of each fragment 1080 as necessary, so that when users switch fragments with the tabs and then return to a previous 1081 fragment, it looks the way it did when they left. For information about saving the state of your 1082 fragment, see the <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> 1083 developer guide.</p> 1084 1085 1086 <p class="note"><strong>Note:</strong> In some cases, the Android system will show your action 1087 bar tabs as a drop-down list in order to ensure the best fit in the action bar.</p> 1088 1089 1090 <h2 id="Dropdown">Adding Drop-down Navigation</h2> 1091 1092 <p>As another mode of navigation (or filtering) within your activity, the action bar offers a 1093 built in drop-down list. For example, the drop-down list can offer different modes by which content 1094 in the activity is sorted.</p> 1095 1096 <!-- 1097 <div class="figure" style="width:135px"> 1098 <img src="{@docRoot}images/ui/actionbar-dropdown.png" alt="" /> 1099 <p class="img-caption"><strong>Figure 5.</strong> Screenshot of a drop-down navigation list in the 1100 action bar.</p> 1101 </div> 1102 --> 1103 1104 <p>The basic procedure to enable drop-down navigation is:</p> 1105 1106 <ol> 1107 <li>Create a {@link android.widget.SpinnerAdapter} that provides the 1108 list of selectable items for the drop-down and the layout to use when drawing each item in the 1109 list.</li> 1110 <li>Implement {@link android.app.ActionBar.OnNavigationListener} to define the behavior that 1111 occurs when the user selects an item from the list.</li> 1112 <li>Enable navigation mode for the action bar with {@link 1113 android.app.ActionBar#setNavigationMode setNavigationMode()}. For example: 1114 <pre> 1115 ActionBar actionBar = getActionBar(); 1116 actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 1117 </pre> 1118 <p class="note"><strong>Note:</strong> You should perform this during your activity's {@link 1119 android.app.Activity#onCreate 1120 onCreate()} method.</p> 1121 </li> 1122 <li>Set the callback for the drop-down list with {@link 1123 android.app.ActionBar#setListNavigationCallbacks setListNavigationCallbacks()}. For example: 1124 <pre> 1125 actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback); 1126 </pre> 1127 <p>This method takes your {@link android.widget.SpinnerAdapter} and {@link 1128 android.app.ActionBar.OnNavigationListener}.</p> 1129 </li> 1130 </ol> 1131 1132 <p>That's the basic setup. However, implementing the {@link android.widget.SpinnerAdapter} and 1133 {@link android.app.ActionBar.OnNavigationListener} is where most of the work is done. There are many 1134 ways you can implement these to define the functionality for your drop-down navigation and 1135 implementing various types of {@link android.widget.SpinnerAdapter} is beyond the scope of this 1136 document (you should refer to the {@link android.widget.SpinnerAdapter} class reference for more 1137 information). However, below is a simple example for a {@link android.widget.SpinnerAdapter} and 1138 {@link android.app.ActionBar.OnNavigationListener} to get you started (click the title to 1139 reveal the sample).</p> 1140 1141 1142 1143 <div class="toggle-content closed"> 1144 1145 <h3 id="Spinner"><a href="#" onclick="return toggleContent(this)"> 1146 <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" alt="" /> 1147 Example SpinnerAdapter and OnNavigationListener 1148 </a></h3> 1149 1150 <div class="toggle-content-toggleme"> 1151 1152 <p>{@link android.widget.SpinnerAdapter} is an adapter that provides data for a spinner widget, 1153 such as the drop-down list in the action bar. {@link android.widget.SpinnerAdapter} is an interface 1154 that you can implement, but Android includes some useful implementations that you can extend, such 1155 as {@link android.widget.ArrayAdapter} and {@link 1156 android.widget.SimpleCursorAdapter}. For example, here's an easy way to create a {@link 1157 android.widget.SpinnerAdapter} by using {@link android.widget.ArrayAdapter} implementation, which 1158 uses a string array as the data source:</p> 1159 1160 <pre> 1161 SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.action_list, 1162 android.R.layout.simple_spinner_dropdown_item); 1163 </pre> 1164 1165 <p>The {@link android.widget.ArrayAdapter#createFromResource createFromResource()} method takes 1166 three parameters: the application {@link android.content.Context}, the resource ID for the string 1167 array, and the layout to use for each list item.</p> 1168 1169 <p>A <a href="{@docRoot}guide/topics/resources/string-resource.html#StringArray">string array</a> 1170 defined in a resource looks like this:</p> 1171 1172 <pre> 1173 <?xml version="1.0" encoding="utf-8"?> 1174 <resources> 1175 <string-array name="action_list"> 1176 <item>Mercury</item> 1177 <item>Venus</item> 1178 <item>Earth</item> 1179 </string-array> 1180 </pre> 1181 </pre> 1182 1183 <p>The {@link android.widget.ArrayAdapter} returned by {@link 1184 android.widget.ArrayAdapter#createFromResource createFromResource()} is complete and ready for you 1185 to pass it to {@link android.app.ActionBar#setListNavigationCallbacks setListNavigationCallbacks()} 1186 (in step 4 from above). Before you do, though, you need to create the {@link 1187 android.app.ActionBar.OnNavigationListener OnNavigationListener}.</p> 1188 1189 1190 <p>Your implementation of {@link android.app.ActionBar.OnNavigationListener} is where you handle 1191 fragment changes or other modifications to your activity when the user selects an item from the 1192 drop-down list. There's only one callback method to implement in the listener: {@link 1193 android.app.ActionBar.OnNavigationListener#onNavigationItemSelected onNavigationItemSelected()}.</p> 1194 1195 <p>The {@link 1196 android.app.ActionBar.OnNavigationListener#onNavigationItemSelected onNavigationItemSelected()} 1197 method receives the position of the item in the list and a unique item ID provided by the {@link 1198 android.widget.SpinnerAdapter}.</p> 1199 1200 <p>Here's an example that instantiates an anonymous implementation of {@link 1201 android.app.ActionBar.OnNavigationListener OnNavigationListener}, which inserts a {@link 1202 android.app.Fragment} into the 1203 layout container identified by {@code R.id.fragment_container}:</p> 1204 1205 <pre> 1206 mOnNavigationListener = new OnNavigationListener() { 1207 // Get the same strings provided for the drop-down's ArrayAdapter 1208 String[] strings = getResources().getStringArray(R.array.action_list); 1209 1210 @Override 1211 public boolean onNavigationItemSelected(int position, long itemId) { 1212 // Create new fragment from our own Fragment class 1213 ListContentFragment newFragment = new ListContentFragment(); 1214 FragmentTransaction ft = openFragmentTransaction(); 1215 // Replace whatever is in the fragment container with this fragment 1216 // and give the fragment a tag name equal to the string at the position selected 1217 ft.replace(R.id.fragment_container, newFragment, strings[position]); 1218 // Apply changes 1219 ft.commit(); 1220 return true; 1221 } 1222 }; 1223 </pre> 1224 1225 <p>This instance of {@link android.app.ActionBar.OnNavigationListener OnNavigationListener} is 1226 complete and you can now call {@link android.app.ActionBar#setListNavigationCallbacks 1227 setListNavigationCallbacks()} (in step 4), passing the {@link android.widget.ArrayAdapter} and this 1228 {@link android.app.ActionBar.OnNavigationListener OnNavigationListener}.</p> 1229 1230 <p>In this example, when the user selects an item from the drop-down list, a fragment is added to 1231 the layout (replacing the current fragment in the {@code R.id.fragment_container} view). The 1232 fragment added is given a tag that uniquely identifies it, which is the same string used to 1233 identify the fragment in the drop-down list.</p> 1234 1235 <p>Here's a look at the {@code ListContentFragment} class that defines each fragment in this 1236 example:</p> 1237 1238 <pre> 1239 public class ListContentFragment extends Fragment { 1240 private String mText; 1241 1242 @Override 1243 public void onAttach(Activity activity) { 1244 // This is the first callback received; here we can set the text for 1245 // the fragment as defined by the tag specified during the fragment transaction 1246 super.onAttach(activity); 1247 mText = getTag(); 1248 } 1249 1250 @Override 1251 public View onCreateView(LayoutInflater inflater, ViewGroup container, 1252 Bundle savedInstanceState) { 1253 // This is called to define the layout for the fragment; 1254 // we just create a TextView and set its text to be the fragment tag 1255 TextView text = new TextView(getActivity()); 1256 text.setText(mText); 1257 return text; 1258 } 1259 } 1260 </pre> 1261 1262 </div><!-- end toggle-content-toggleme --> 1263 1264 </div><!-- end toggle-content --> 1265 1266 1267 1268 1269 1270 <h2 id="Style">Styling the Action Bar</h2> 1271 1272 <p>If you've implemented a custom design for the widgets in your application, you might 1273 also want to redesign some of the action bar to match your app design. To do so, you need to use 1274 Android's <a 1275 href="{@docRoot}guide/topics/ui/themes.html">style and theme</a> framework to restyle the action 1276 bar using special style properties.</p> 1277 1278 1279 <p class="note"><strong>Note:</strong> In order for background images to change appearance 1280 depending on the current button state (selected, pressed, unselected), the drawable resource you use 1281 must be a <a href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">state 1282 list drawable</a>.</p> 1283 1284 <p class="caution"><strong>Caution:</strong> For all background drawables you provide, be sure to use <a 1285 href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">Nine-Patch drawables</a> to allow 1286 stretching. The Nine-Patch image should be <em>smaller</em> than 40px tall and 30px wide (for the mdpi asset).</p> 1287 1288 1289 <h3 id="GeneralStyles">General appearance</h3> 1290 1291 <dl> 1292 1293 <dt>{@link android.R.attr#windowActionBarOverlay 1294 android:windowActionBarOverlay}</dt> 1295 <dd>Declares whether the action bar should overlay the activity layout rather than offset the 1296 activity's layout position (for example, the Gallery app uses overlay mode). This is 1297 {@code false} by default. 1298 <p>Normally, the action bar requires its own space on the screen and your activity layout fills in 1299 what's left over. When the action bar is in overlay mode, your activity layout uses all the 1300 available space and the system draws the action bar on top. Overlay mode can be useful if you want 1301 your content to keep a fixed size and position when the action bar is hidden and shown. You might 1302 also like to use it purely as a visual effect, because you can use a semi-transparent background 1303 for the action bar so the user can still see some of your activity layout behind the action 1304 bar.</p> 1305 <p class="note"><strong>Note:</strong> The {@link android.R.style#Theme_Holo Holo} theme families 1306 draw the action bar with a semi-transparent background by default. However, you can modify it with 1307 your own styles and the {@link android.R.style#Theme_DeviceDefault DeviceDefault} theme on 1308 different devices might use an opaque background by default.</p> 1309 <p>When overlay mode is enabled, your activity layout has no awareness of the action bar laying on 1310 top of it. So, you must be careful not to place any important information or UI components in the 1311 area overlayed by the action bar. If appropriate, you can refer to the platform's value for {@link 1312 android.R.attr#actionBarSize} to determine the height of the action bar, by referencing it 1313 in your XML layout. For example:</p> 1314 <pre> 1315 <SomeView 1316 ... 1317 android:layout_marginTop="?android:attr/actionBarSize" /> 1318 </pre> 1319 <p>You can also retrieve the action bar height at runtime with {@link 1320 android.app.ActionBar#getHeight()}. This reflects the height of the action bar at the time it's 1321 called, which might not include the stacked action bar (due to navigation tabs) if called during early 1322 activity lifecycle methods. To see how you can determine the total height at runtime, including the 1323 stacked action bar, see the <a 1324 href="{@docRoot}resources/samples/HoneycombGallery/src/com/example/android/hcgallery/TitlesFragment.html" 1325 >{@code TitlesFragment}</a> class in the <a 1326 href="{@docRoot}resources/samples/HoneycombGallery/index.html" 1327 >Honeycomb Gallery</a> sample app.</p> 1328 </dd> 1329 1330 </dl> 1331 1332 1333 <h3 id="ActionItemStyles">Action items</h3> 1334 1335 <dl> 1336 <dt>{@link android.R.attr#actionButtonStyle 1337 android:actionButtonStyle}</dt> 1338 <dd>Defines a style resource for the action item buttons.</dd> 1339 1340 <dt>{@link android.R.attr#actionBarItemBackground 1341 android:actionBarItemBackground}</dt> 1342 <dd>Defines a drawable resource for each action item's background. (Added in API level 14.)</dd> 1343 1344 <dt>{@link android.R.attr#itemBackground 1345 android:itemBackground}</dt> 1346 <dd>Defines a drawable resource for each overflow menu item's background.</dd> 1347 1348 <dt>{@link android.R.attr#actionBarDivider 1349 android:actionBarDivider}</dt> 1350 <dd>Defines a drawable resource for the divider between action items. (Added in API level 1351 14.)</dd> 1352 1353 <dt>{@link android.R.attr#actionMenuTextColor 1354 android:actionMenuTextColor}</dt> 1355 <dd>Defines a color for text that appears in an action item.</dd> 1356 1357 <dt>{@link android.R.attr#actionMenuTextAppearance 1358 android:actionMenuTextAppearance}</dt> 1359 <dd>Defines a style resource for text that appears in an action item.</dd> 1360 1361 <dt>{@link android.R.attr#actionBarWidgetTheme 1362 android:actionBarWidgetTheme}</dt> 1363 <dd>Defines a theme resource for widgets that are inflated into the action bar as <a 1364 href="#ActionView">action views</a>. (Added in API level 14.)</dd> 1365 </dl> 1366 1367 1368 <h3 id="NavigationStyles">Navigation tabs</h3> 1369 1370 <dl> 1371 <dt>{@link android.R.attr#actionBarTabStyle 1372 android:actionBarTabStyle}</dt> 1373 <dd>Defines a style resource for tabs in the action bar.</dd> 1374 1375 <dt>{@link android.R.attr#actionBarTabBarStyle 1376 android:actionBarTabBarStyle}</dt> 1377 <dd>Defines a style resource for the thin bar that appears below the navigation tabs.</dd> 1378 1379 <dt>{@link android.R.attr#actionBarTabTextStyle 1380 android:actionBarTabTextStyle}</dt> 1381 <dd>Defines a style resource for text in the navigation tabs.</dd> 1382 </dl> 1383 1384 1385 <h3 id="DropDownStyles">Drop-down lists</h3> 1386 1387 <dl> 1388 <dt>{@link android.R.attr#actionDropDownStyle 1389 android:actionDropDownStyle}</dt> 1390 <dd>Defines a style for the drop-down navigation (such as the background and text styles).</dd> 1391 </dl> 1392 1393 1394 1395 <p>For example, here's a file that defines a few custom styles for the action bar:</p> 1396 1397 <pre> 1398 <?xml version="1.0" encoding="utf-8"?> 1399 <resources> 1400 <!-- the theme applied to the application or activity --> 1401 <style name="CustomActivityTheme" parent="@android:style/Theme.Holo"> 1402 <item name="android:actionBarTabTextStyle">@style/CustomTabTextStyle</item> 1403 <item name="android:actionBarDivider">@drawable/ab_divider</item> 1404 <item name="android:actionBarItemBackground">@drawable/ab_item_background</item> 1405 </style> 1406 1407 <!-- style for the action bar tab text --> 1408 <style name="CustomTabTextStyle"> 1409 <item name="android:textColor">#2456c2</item> 1410 </style> 1411 </resources> 1412 </pre> 1413 1414 <p class="note"><strong>Note:</strong> Be certain that your theme declares a parent theme in the 1415 {@code <style>} tag, from which it inherits all styles not explicitly declared by your theme. 1416 When modifying the action bar, using a parent theme is important so that you can simply override the 1417 action bar styles you want to change without re-implementing the styles you want to leave alone 1418 (such as text appearance or padding in action items).</p> 1419 1420 <p>You can apply your custom theme to the entire application or to individual activities in your 1421 manifest file like this:</p> 1422 1423 <pre> 1424 <application android:theme="@style/CustomActivityTheme" 1425 ... /> 1426 </pre> 1427 1428 <p>For more information about using style and theme resources in your application, read <a 1429 href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a>.</p> 1430 1431 1432 <h3 id="AdvancedStyles">Advanced styling</h3> 1433 1434 <p>If you need more advanced styling for the action bar than is available with the 1435 properties above, you can include {@link android.R.attr#actionBarStyle android:actionBarStyle} and 1436 {@link android.R.attr#actionBarSplitStyle android:actionBarSplitStyle} in your activity's theme. 1437 Each of these specifies another style that can define various properties for the action bar, 1438 including different backgrounds with {@link android.R.attr#background android:background}, {@link 1439 android.R.attr#backgroundSplit android:backgroundSplit}, and {@link android.R.attr#backgroundStacked 1440 android:backgroundStacked}. If you override these action bar styles, be sure that you define a 1441 parent action bar style such as {@link android.R.style#Widget_Holo_ActionBar 1442 Widget.Holo.ActionBar}.</p> 1443 1444 <p>For example, if you want to change the action bar's background, you could use the following 1445 styles:</p> 1446 1447 <pre> 1448 <?xml version="1.0" encoding="utf-8"?> 1449 <resources> 1450 <!-- the theme applied to the application or activity --> 1451 <style name="CustomActivityTheme" parent="@android:style/Theme.Holo"> 1452 <item name="android:actionBarTabTextStyle">@style/customTabTextStyle</item> 1453 <!-- other activity and action bar styles here --> 1454 </style> 1455 1456 <!-- style for the action bar, simply to change the background --> 1457 <style parent="@android:style/Widget.Holo.ActionBar"> 1458 <item name="android:background">@drawable/ab_background</item> 1459 <item name="android:backgroundSplit">@drawable/ab_background</item> 1460 </style> 1461 </resources> 1462 </pre> 1463 1464 1465 1466 1467 1468