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