IMPORTANT: Per accedir als fitxer de subversion: http://acacha.org/svn (sense password). Poc a poc s'aniran migrant els enllaços. Encara però funciona el subversion de la farga però no se sap fins quan... (usuari: prova i la paraula de pas 123456)

Introducció

NOTA: És interessant entendre i llegir abans sobre els menús Android ja que en certa manera les Action Bar són un "subtipus de menú". A més cal tenir en compte que històricament primer hi havia només menús i actualment (--acacha (discussió) 15:56, 17 gen 2013 (CET)) hi ha tant Action Bars com menús

La barra d'accions (aka Action bar) és una característica d'Android que identifica l'aplicació i la situació de l'usuari alhora que proveeix d'accions d'usuari i modes de navegació. La barra es pot trobar a la majoria d'activitats a les que és important mostrar als usuaris les accions que es poden dur a terme i les opcions de navegació per l'aplicació.

La barra s'ha convertit en un paradigma de disseny que permet oferir als usuaris interfícies consistents entre diferents aplicacions. A més el sistema adapta de forma automàtica l'apariència de la barra per a diferents configuracions de pantalla.

Existeix una API especifica per a la barra d'accions que es va afegir a la versió 3.0 d'Android (API level 11)

Els objectius principals de la barra de navegació són:

  • Proveir d'un espai dedicat a la pantalla per tal d'identificar la marca de l'aplicació (aka brand) i la localització de l'usuari dins l'aplicació. això s'aconsegueix amb l'icona o logo de l'aplicació que apareix a l'esquerra del titol de l'activitat (tot això es però configurable)
  • Proveïx d'una navegació consistent i un refinament de la vista (View) entre diferents aplicacions. La barra d'acció porta un navegadors de pestanyes (tag navigation) incorporat que permet canviar entre els diferents fragments de l'aplicació de forma ràpida. També ofereix un llista desplegable ( drop-down list) que es pot utilitzar com una alternativa de navegació o per refinar la vista actual.
  • Fa que les accions principals (com cercar, crear, compartir, etc) tinguin un espai prominent i siguin accesibles per a l'usuari d'un forma previsible. Es pot proporcionar accés instantani a les accions d'usuari claus col·locant-les a la barra d'accions com a action items. Els Action items també poden proporcionar una action view, que mostra un widget encastat per tal de mostrar encara més possibles accions. Els items de menú que no són promocionats a la barra d'accions es troben disponibles al overflow menu, que es pot mostrar mitjançant el botó de Menú del dispositiu ( quan es troba disponible) o per un botó que apareix a la barra d'acció (quan el dispositiu no té botó de menú). Vegeu un exemple (per a més informació vegeu Menu guide):

La següent imatge mostra un exemple d'Action bar:

actionbar.png

Recursos:

Manifest.xml

Amb Android 3.0 (API level 11), la barra d'accions s'inclou a totes les activitats que utilitzen el tema Android Theme.Holo (o un dels temes que hi són descendents). Aquest és el tema per defecte quan els atributs targetSdkVersion o el minSdkVersion es 11 o superior. Un exemple:

<manifest ... >
    <uses-sdk android:minSdkVersion="4"
              android:targetSdkVersion="11" />
    ...
</manifest>

A l'exemple l'aplicació requereix una versió API level mínima de 4 ( Android 1.6), però també fa un target a API level 11 (Android 3.0). D'aquesta manera quan s'executa en un Android 3.0 o superior el sistema aplica el tema holographic per a cada activitat i per tant cada activitat té el Action Bar.

Vegeu també Android Support

Estructura

La barra d'accions és una barra que sol sortir de forma permanent a la part superior de l'aplicació (és a dir apareix a totes les Activitats o Fragments de la app Android).

La següent imatge mostra els components de la barra d'accions:

TODO: imatge: action_bar_basics.png
  • App icon: Estableix la identitat de l'aplicació Android. També serveix per navegar per l'aplicació i permet establir un Navigation Pattern (patró de navegació). Vegeu [1]
  • View control: Si la nostra aplicació mostra les dades en diferents vistes Android (per exemple quelcom similar a les pestanyes), aquest segment de la barra de navegació permet als usuaris intercanviar de vista. Es poden fer a mida però solen ser drop-down menus o tab controls. Sinó hi ha vistes es pot utilitzar aquest fragment de l'action bar per mostrar un títol o també quelcom que identifiqui la marca (branding) de la vostra aplicació.
  • Action buttons': Les accions més importants de la nostra aplicació es mostren en aquesta secció. Les accions que no caben aquó es mouen automàticament al menú action overflow. Es pot fer un long press en l'icona d'una acció per tal de veure el seu nom.
  • Action overflow: Es mostra per aquelles accions que s'utilitzen menys sovint i/o que no caben al fragment Action Buttons.

Exemples

Afegir una Action bar

Des de la versió Android 3.0 (API level 11), la barra d'acció s'inclou per defecte a totes les activitats que utilitzen el tema:

Theme.Holo

O qualsevol tema que en sigui un descendent. Aquest tema és el tema per defecte quan qualsevol dels atributs:

 targetSdkVersion

o

minSdkVersion

té un valor de 11 o superior al fitxer de manifest.

 <manifest ... >
    <uses-sdk android:minSdkVersion="4"
              android:targetSdkVersion="11" />
    ...
 </manifest>

Eliminar la barra d'accions

Si no es vol utilitzar la barra d'accions per a una activitat en particular, aleshores cal utilitzar el tema:

Theme.Holo.NoActionBar

Per exemple:

 <activity android:theme="@android:style/Theme.Holo.NoActionBar">

En temps d'execució també es pot amagar la barra amb el mètode

hide()

Per exemple:

 ActionBar actionBar = getActionBar();
 actionBar.hide();

Es pot tornar a mostrar amb:

show()

NOTA: Si l'activitat ha de mostrar i amagar molt sovint la barra d'accions es recomana utilitzar el move overlay:

android:windowActionBarOverlay=true

També es pot posar l'estil:

android:windowActionBar=false

Però aleshores no podreu utilitzar en cap moment la barra d'acció a aquesta activitat (getActionBar() retorna null)

Afegir Action items

Els items d'acció de la barra d'acció no són més que ítems del menú que han estat "promocionats" a la barra d'accions. Això es pot fer declarant que el menu item és de tipus:

action item

Un ítem d'acció pot incloure una icona i/o un text. La resta de ítems apareixen al overflow menu que es mostra utilitzant el Menu button (si el dispositiu en té) o amb un botó adicional.

actionbar-item-withtext.png

Quan l'activitat s'inicia per primer com omple la barra d'acció cridant a la funció:

onCreateOptionsMenu()

de l'activitat (vegeu també Menus developer guide). Vegem un exemple:

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_activity, menu);
    return true;
 }

Al fitxer XML es pot demanar a un ítem que aparegui si hi ha espai amb:

android:showAsAction="ifRoom"

Per a l'element:

<item>

Si no hi ha prou espai es mostra al overflow menu.

Si l'ítem proporciona una icona:

android:icon

i una títol:

android:title

Aleshores només es mostra la icona. Si es vol mostrar el text cal utilitzar withText a:

android:showAsAction

Un exemple:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_save"
          android:icon="@drawable/ic_menu_save"
          android:title="@string/menu_save"
          android:showAsAction="ifRoom|withText" />
</menu>

Quan un usuari selecciona un item aleshores es crida el mètode:

onOptionsItemSelected()

Passant el ID (android:id) del item seleccionat.

IMPORTANT: Cal sempre definir android:title per cada ítem de menú per 3 raons:

  • si no hi ha prou espai per mostra l'acció es mostrarà pel seu nom al overflow menu.
  • Per temes d'accesibilitat ( els Screen readers llegeixen l'ítem)
  • Per mostrar un tip amb la descripció quan es va un long-press sobre l'icona.

NOTA: If you added the menu item from a fragment, via the Fragment class's onCreateOptionsMenu callback, then the system calls the respective onOptionsItemSelected() method for that fragment when the user selects one of the fragment's items. However the activity gets a chance to handle the event first, so the system calls onOptionsItemSelected() on the activity before calling the same callback for the fragment.

També es pot declarar un item per apareixer sempre amb el valor always.


Escollint els menú ítems correctes per esdevenir action items

Els criteris per "promocionar" un ítem de menú a un action item són, per ordre d'importància (afa FIT scheme):

  • Frequently used: It's an action that your users need seven out of ten visits or they use it several times in a row. Example frequent actions: "New message" in the Messaging app and "Search" on Google Play.
  • Important: It's an action that you need users to easily discover or, if it's not frequently used, it's important that it be effortless to perform in the few cases that users do need it. Example important actions: "Add network" in Wi-Fi settings and "Switch to camera" in the Gallery app.
  • Typical: It's an action that is typically provided in the action bar in similar apps, so your users expect to find it in yours. Example typical actions: "Refresh" in an email or social app, and "New contact" in the People app.

Es recomana no posar més de 4 accions. Inclús si es té espai a la pantall no és recomana posar moltes accions co ma criteri de disseny.

També es recomana no posar mai les següents accions:

Settings/Preferències
Help/Ajuda
Feedback

i similars. Aquestes sempre han d'anar al overflow menu.

NOTA: Remember that not all devices provide a dedicated hardware button for Search, so if it's an important feature in your app, it should always appear as an action item (and usually as the first item, especially if you offer it with an action view

NOTA: Menu items vs. other app controls. As a general rule, all items in the options menu (let alone action items) should have a global impact on the app, rather than affect only a small portion of the interface. For example, if you have a multi-pane layout and one pane shows a video while another lists all videos, the video player controls should appear within the pane containing the video (not in the action bar), while the action bar might provide action items to share the video or save the video to a favorites list. So, even before deciding whether a menu item should appear as an action item, be sure that the item has a global scope for the current activity. If it doesn't, then you should place it as a button in the appropriate context of the activity layout.

Com utilitzar el logo de l'aplicació per a navegar

Per defecte es mostra el logo de l'aplicació a l'Action bar, de fet és l'atribut XML:

android:icon

especificat al element XML:

<application>

o

<activity>

Del fitxer de manifest. O s'utilitza:

android:logo

Si s'ha especificat el logo. Les icones són quadrades, els logos no tenen per que ser-ho

Es pot activar que la icona sigui un element actiu, per típicament:

  • Anar a la home de l'aplicació (per exemple un dashboard o similar)
  • Navegar amunt en la estructura de navegació de la vostra aplicació

Al fer un touch a la icona es crida el mètode:

onOptionsItemSelected()

Amb el resource ID:

android.R.id.home

IMPORTANT: Si es vol tornar al menú home cal incloure el flag FLAG_ACTIVITY_CLEAR_TOP al Intent.Això es fa per evitar que es tinguin obertes múltiples instàncies de la Home

Tornar a la home

Vegem un exemple de com tornar a la Home:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            // app icon in action bar clicked; go home
            Intent intent = new Intent(this, HomeActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

Si s'accepten intents provinents d'altres aplicacions cal posar també el flag FLAG_ACTIVITY_NEW_TASK.

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);

Per més info vegeu: [2]

NOTA: A partir de la versió 4.0, cal activar l'icona explícitament cridant setHomeButtonEnabled(true). Abans era l'opció per defecte

Tornar enrere

La següent imatge mostra les diferències en la icona de l'aplicació depenent de si estem a l'arrel o podem pujar un nivell:

action_bar_pattern_up_app_icon.png

Més imatges:

actionbar-logo.png

A més de la navegació "tradiciona" amb el boto back que ens porta a la pantalla prèvia (per ordre cronològic), també podem oferir el action bar icon com a opció per a fer un up, que permet pujar un nivell en la jerarquia de la nostra aplicació.

Per activar la icona de la navegació amunt, utilitzeu el mètode:

setDisplayHomeAsUpEnabled(true)

Un exemple:

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
 
    setContentView(R.layout.main);
    ActionBar actionBar = getActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    ...
 }

Quan l'usuari premi el logo, es cridarà al mètode:

onOptionsItemSelected()

amb el resource Id:

android.R.id.home

Tal i com s'ha explicat a l'anterior apartat d'aquesta wiki.

NOTA: Remember to use the FLAG_ACTIVITY_CLEAR_TOP flag in the Intent, so that you don't create a new instance of the parent activity if one already exists. For instance, if you don't use the FLAG_ACTIVITY_CLEAR_TOP flag, then after navigating up, the BACK button will actually take the user "forward", with respect to the application structure, which would be strange.

ViewPagerindicator

Permet tenir un indicador clar que hi han més tabs (pestanyes) a la dreta o esquerre i permet tenir tabs a l'estil de l'app Google Play.

Proporciona un widget que indica que hi ha més pàgines quan utilitzem ViewPager de la llibreria Android Support o també amb ActionBarSherlock.

Vegeu:

http://viewpagerindicator.com/

Hi han exemples. Sinó podeu utilitzar:

Include one of the widgets in your view. This should usually be placed adjacent to the ViewPager it represents.

   <com.viewpagerindicator.TitlePageIndicator
   	android:id="@+id/titles"
   	android:layout_height="wrap_content"
   	android:layout_width="fill_parent" />
   In your onCreate method (or onCreateView for a fragment), bind the indicator to the ViewPager.
   //Set the pager with an adapter
   ViewPager pager = (ViewPager)findViewById(R.id.pager);
   pager.setAdapter(new TestAdapter(getSupportFragmentManager()));
   //Bind the title indicator to the adapter
   TitlePageIndicator titleIndicator = (TitlePageIndicator)findViewById(R.id.titles);
   titleIndicator.setViewPager(pager);
   (Optional) If you use an OnPageChangeListener with your view pager you should set it in the indicator rather than on the pager directly.
   //continued from above
   titleIndicator.setOnPageChangeListener(mPageChangeListener);

For more examples please take a look at the source code to the samples.

Afegint un Action View

Figure 7. An action bar with a collapsed action view for Search (top), then expanded action view with the SearchView widget (bottom).

An action view is a widget that appears in the action bar as a substitute for an action item's button. For example, if you have an item in the options menu for "Search," you can add an action view that replaces the button with a SearchView widget, as shown in figure 7.

To declare an action view for an item in your menu resource, use either the android:actionLayout or android:actionViewClass attribute to specify either a layout resource or widget class to use, respectively. For example:

<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android">

   <item android:id="@+id/menu_search"
         android:title="@string/menu_search"
         android:icon="@drawable/ic_menu_search"
         android:showAsAction="ifRoom|collapseActionView"
         android:actionViewClass="android.widget.SearchView" />

</menu>

Notice that the android:showAsAction attribute also includes "collapseActionView". This is optional and declares that the action view should be collapsed into a button. When the user selects the button, the action view expands. Otherwise, the action view is visible by default and might consume valuable action bar space even when the user is not using it. For more information, see the next section about Handling collapsible action views.

If you need to add some event hooks to your action view, you can do so during the onCreateOptionsMenu() callback. You can acquire elements in an action view by calling findItem() with the ID of the menu item, then call getActionView(). For example, the search widget from the above sample is acquired like this:

@Override public boolean onCreateOptionsMenu(Menu menu) {

   getMenuInflater().inflate(R.menu.options, menu);
   SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
   // Configure the search info and add any event listeners
   ...
   return super.onCreateOptionsMenu(menu);

}

For more information about using the search widget, see Creating a Search Interface. Handling collapsible action views Supporting Android 3.0 with an action view

The "collapseActionView" option was added with Android 4.0 (API level 14). However, if your application supports older versions, you should still declare "collapseActionView" in order to better support smaller screens. Devices running Android 4.0 and higher will show the action view collapsed, while older versions work as designed otherwise.

Adding this value requires that you set your build target to Android 4.0 or higher in order to compile. Older versions of Android ignore the "collapseActionView" value because they don't understand it. Just be sure not to use other APIs in your source code that are not supported in the version declared by your minSdkVersion, unless you add the appropriate version check at runtime.

Action views allow you to provide fast access to rich actions without changing activities or fragments, or replacing the action bar. However, it might not be appropriate to make an action view visible by default. To preserve the action bar space (especially when running on smaller screens), you can collapse your action view into an action item button. When the user selects the button, the action view appears in the action bar. When collapsed, the system might place the item into the overflow menu if you've defined android:showAsAction with "ifRoom", but the action view still appears in the action bar when the user selects the item. You can make your action view collapsible by adding "collapseActionView" to the android:showAsAction attribute, as shown in the XML above.

Because the system will expand the action view when the user selects the item, so you do not need to respond to the item in the onOptionsItemSelected callback. The system still calls onOptionsItemSelected() when the user selects it, but the system will always expand the action view unless you return true (indicating you've handled the event instead).

The system also collapses your action view when the user selects the "up" icon in the action bar or presses the BACK button.

If necessary, you can expand or collapse the action view in your own code by calling expandActionView() and collapseActionView() on the MenuItem.

Note: Although collapsing your action view is optional, we recommend that you always collapse your action view if it includes SearchView. Also be aware that some devices provide a dedicated SEARCH button and you should expand your search action view if the user presses the SEARCH button. Simply override your activity's onKeyUp() callback method, listen for the KEYCODE_SEARCH event, then call expandActionView().

If you need to update your activity based on the visibility of your action view, you can receive callbacks when it's expanded and collapsed by defining an OnActionExpandListener and registering it with setOnActionExpandListener(). For example:

@Override public boolean onCreateOptionsMenu(Menu menu) {

   getMenuInflater().inflate(R.menu.options, menu);
   MenuItem menuItem = menu.findItem(R.id.actionItem);
   ...
   menuItem.setOnActionExpandListener(new OnActionExpandListener() {
       @Override
       public boolean onMenuItemActionCollapse(MenuItem item) {
           // Do something when collapsed
           return true;  // Return true to collapse action view
       }
       @Override
       public boolean onMenuItemActionExpand(MenuItem item) {
           // Do something when expanded
           return true;  // Return true to expand action view
       }
   });

}

Adding an Action Provider

Figure 8. Screenshot from the Gallery app, with the ShareActionProvider submenu expanded to show share targets.

Similar to an action view, an action provider (defined by the ActionProvider class) replaces an action item with a customized layout, but it also takes control of all the item's behaviors. When you declare an action provider for a menu item in the action bar, it not only controls the appearance of the item in the action bar with a custom layout, but also handles the default event for the menu item when it appears in the overflow menu. It can also provide a submenu from either the action bar or the overflow menu.

For example, the ShareActionProvider is an extension of ActionProvider that facilitates a “share" action by showing a list of available share targets from the action bar. Instead of using a traditional action item that invokes the ACTION_SEND intent, you can declare an instance of ShareActionProvider to handle an action item. This action provider presents an action view with a drop-down list of applications that handle the ACTION_SEND intent, even when the menu item appears in the overflow menu. Hence, when you use an action provider such as this one, you don't have to handle user events on the menu item.

To declare an action provider for an action item, define the android:actionProviderClass attribute for the appropriate the <item> element in your menu resource, using the fully-qualified class name of the action provider. For example:

<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android">

   <item android:id="@+id/menu_share"
         android:title="@string/share"
         android:showAsAction="ifRoom"
         android:actionProviderClass="android.widget.ShareActionProvider" />
   ...

</menu>

In this example, the ShareActionProvider is used as the action provider. At this point, the action provider officially takes control of the menu item and handles both its appearance and behavior in the action bar and its behavior in the overflow menu. You must still provide a text title for the item to be used in the overflow menu.

Although the action provider can perform the default action for the menu item when it appears in the overflow menu, your activity (or fragment) can override that behavior by also handling the click event from the onOptionsItemSelected() callback method. If you do not handle the event in that callback, then the action provider receives the onPerformDefaultAction() callback to handle the event. However, if the action provider provides a submenu, then your activity will not receive the onOptionsItemSelected() callback, because the submenu is shown instead of invoking the default menu item behavior when selected. Using the ShareActionProvider

If you want to provide a "share" action in your action bar by leveraging other applications installed on the device (for example, to share a photo using a messaging or social app), then using ShareActionProvider is an effective way to do so, rather than adding an action item that invokes the ACTION_SEND intent. When you use ShareActionProvider for an action item, it presents an action view with a drop-down list of applications that handle the ACTION_SEND intent (as shown in figure 8).

All the logic for creating the submenu, populating it with share targets, and handling click events (including when the item appears in the overflow menu) is implemented by the ShareActionProvider—the only code you need to write is to declare the action provider for the menu item and specify the share intent.

By default, the ShareActionProvider retains a ranking for each share target based on how often the user selects each one. The share targets used more frequently appear at the top of the drop-down list and the target used most often appears directly in the action bar as the default share target. By default, the ranking information is saved in a private file with a name specified by DEFAULT_SHARE_HISTORY_FILE_NAME. If you use the ShareActionProvider or an extension of it for only one type of action, then you should continue to use this default history file and there's nothing you need to do. However, if you use ShareActionProvider or an extension of it for multiple actions with semantically different meanings, then each ShareActionProvider should specify its own history file in order to maintain its own history. To specify a different history file for the ShareActionProvider, call setShareHistoryFileName() and provide an XML file name (for example, "custom_share_history.xml").

Note: Although the ShareActionProvider ranks share targets based on frequency of use, the behavior is extensible and extensions of ShareActionProvider can perform different behaviors and ranking based on the history file (if appropriate).

To add ShareActionProvider, simply define the android:actionProviderClass attribute with "android.widget.ShareActionProvider", as shown in the XML example above. The only thing left to do is define the Intent you want to use for sharing. To do so, you must call getActionProvider() to retrieve the ShareActionProvider that's associated with a MenuItem, then call setShareIntent().

If the format for the share intent depends on the selected item or other variables that change during the activity lifecycle, you should save the ShareActionProvider in a member field and update it by calling setShareIntent() as necessary. For example:

private ShareActionProvider mShareActionProvider; ...

@Override public boolean onCreateOptionsMenu(Menu menu) {

   mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share).getActionProvider();
   // If you use more than one ShareActionProvider, each for a different action,
   // use the following line to specify a unique history file for each one.
   // mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
   // Set the default share intent
   mShareActionProvider.setShareIntent(getDefaultShareIntent());
   return true;

} // When you need to update the share intent somewhere else in the app, call // mShareActionProvider.setShareIntent()

The ShareActionProvider now handles all user interaction with the item and you do not need to handle click events from the onOptionsItemSelected() callback method.

For a sample using the share action provider, see ActionBarShareActionProviderActivity. Creating a custom action provider

When you want to create an action view that has dynamic behaviors and a default action in the overflow menu, extending ActionProvider to define those behaviors is a good solution. Creating your own action provider offers you an organized and reusable component, rather than handling the various action item transformations and behaviors in your fragment or activity code. As shown in the previous section, Android provides one implementation of ActionProvider for share actions: the ShareActionProvider.

To create your own, simply extend the ActionProvider class and implement its callback methods as appropriate. Most importantly, you should implement the following:

ActionProvider()

   This constructor passes you the application Context, which you should save in a member field to use in the other callback methods.

onCreateActionView()

   This is where you define the action view for the item. Use the Context acquired from the constructor to instantiate a LayoutInflater and inflate your action view layout from an XML resource, then hook up event listeners. For example:
   public View onCreateActionView() {
       // Inflate the action view to be shown on the action bar.
       LayoutInflater layoutInflater = LayoutInflater.from(mContext);
       View view = layoutInflater.inflate(R.layout.action_provider, null);
       ImageButton button = (ImageButton) view.findViewById(R.id.button);
       button.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               // Do something...
           }
       });
       return view;
   }

onPerformDefaultAction()

   The system calls this when the menu item is selected from the overflow menu and the action provider should perform a default action for the menu item.
   However, if your action provider provides a submenu, through the onPrepareSubMenu() callback, then the submenu appears even when the menu item is in the overflow menu. Thus, onPerformDefaultAction() is never called when there is a submenu.
   Note: An activity or a fragment that implements onOptionsItemSelected() can override the action provider's default behavior by handling the item-selected event (and returning true), in which case, the system does not call onPerformDefaultAction().

For an example extension of ActionProvider, see ActionBarSettingsActionProviderActivity.

Adding Drop-down Navigation

As another mode of navigation (or filtering) within your activity, the action bar offers a built in drop-down list. For example, the drop-down list can offer different modes by which content in the activity is sorted.

The basic procedure to enable drop-down navigation is:

   Create a SpinnerAdapter that provides the list of selectable items for the drop-down and the layout to use when drawing each item in the list.
   Implement ActionBar.OnNavigationListener to define the behavior that occurs when the user selects an item from the list.
   Enable navigation mode for the action bar with setNavigationMode(). For example:
   ActionBar actionBar = getActionBar();
   actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
   Note: You should perform this during your activity's onCreate() method.
   Set the callback for the drop-down list with setListNavigationCallbacks(). For example:
   actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);
   This method takes your SpinnerAdapter and ActionBar.OnNavigationListener.

That's the basic setup. However, implementing the SpinnerAdapter and ActionBar.OnNavigationListener is where most of the work is done. There are many ways you can implement these to define the functionality for your drop-down navigation and implementing various types of SpinnerAdapter is beyond the scope of this document (you should refer to the SpinnerAdapter class reference for more information). However, below is a simple example for a SpinnerAdapter and ActionBar.OnNavigationListener to get you started (click the title to reveal the sample). Example SpinnerAdapter and OnNavigationListener

Canviant l'estil de l'Action Bar

If you've implemented a custom design for the widgets in your application, you might also want to redesign some of the action bar to match your app design. To do so, you need to use Android's style and theme framework to restyle the action bar using special style properties.

Note: In order for background images to change appearance depending on the current button state (selected, pressed, unselected), the drawable resource you use must be a state list drawable.

Caution: For all background drawables you provide, be sure to use Nine-Patch drawables to allow stretching. The Nine-Patch image should be smaller than 40px tall and 30px wide (for the mdpi asset).

Recursos:

General appearance

android:windowActionBarOverlay

   Declares whether the action bar should overlay the activity layout rather than offset the activity's layout position (for example, the Gallery app uses overlay mode). This is false by default.
   Normally, the action bar requires its own space on the screen and your activity layout fills in what's left over. When the action bar is in overlay mode, your activity layout uses all the available space and the system draws the action bar on top. Overlay mode can be useful if you want your content to keep a fixed size and position when the action bar is hidden and shown. You might also like to use it purely as a visual effect, because you can use a semi-transparent background for the action bar so the user can still see some of your activity layout behind the action bar.
   Note: The Holo theme families draw the action bar with a semi-transparent background by default. However, you can modify it with your own styles and the DeviceDefault theme on different devices might use an opaque background by default.
   When overlay mode is enabled, your activity layout has no awareness of the action bar laying on top of it. So, you must be careful not to place any important information or UI components in the area overlayed by the action bar. If appropriate, you can refer to the platform's value for actionBarSize to determine the height of the action bar, by referencing it in your XML layout. For example:
   <SomeView
       ...
       android:layout_marginTop="?android:attr/actionBarSize" />
   You can also retrieve the action bar height at runtime with getHeight(). This reflects the height of the action bar at the time it's called, which might not include the stacked action bar (due to navigation tabs) if called during early activity lifecycle methods. To see how you can determine the total height at runtime, including the stacked action bar, see the TitlesFragment class in the Honeycomb Gallery sample app.

Action items

android:actionButtonStyle

   Defines a style resource for the action item buttons.

android:actionBarItemBackground

   Defines a drawable resource for each action item's background. (Added in API level 14.)

android:itemBackground

   Defines a drawable resource for each overflow menu item's background.

android:actionBarDivider

   Defines a drawable resource for the divider between action items. (Added in API level 14.)

android:actionMenuTextColor

   Defines a color for text that appears in an action item.

android:actionMenuTextAppearance

   Defines a style resource for text that appears in an action item.

android:actionBarWidgetTheme

   Defines a theme resource for widgets that are inflated into the action bar as action views. (Added in API level 14.)

Navigation tabs

android:actionBarTabStyle

   Defines a style resource for tabs in the action bar.

android:actionBarTabBarStyle

   Defines a style resource for the thin bar that appears below the navigation tabs.

android:actionBarTabTextStyle

   Defines a style resource for text in the navigation tabs.

Drop-down lists

android:actionDropDownStyle

   Defines a style for the drop-down navigation (such as the background and text styles).

For example, here's a file that defines a few custom styles for the action bar:

<?xml version="1.0" encoding="utf-8"?> <resources>

   <style name="CustomActivityTheme" parent="@android:style/Theme.Holo">
       <item name="android:actionBarTabTextStyle">@style/CustomTabTextStyle</item>
       <item name="android:actionBarDivider">@drawable/ab_divider</item>
       <item name="android:actionBarItemBackground">@drawable/ab_item_background</item>
   </style>
   <style name="CustomTabTextStyle" parent="@android:style/TextAppearance.Holo">
       <item name="android:textColor">#2456c2</item>
   </style>

</resources>

Note: Be certain that your theme declares a parent theme in the <style> tag, from which it inherits all styles not explicitly declared by your theme. When modifying the action bar, using a parent theme is important so that you can simply override the action bar styles you want to change without re-implementing the styles you want to leave alone (such as text appearance or padding in action items).

You can apply your custom theme to the entire application or to individual activities in your manifest file like this:

<application android:theme="@style/CustomActivityTheme" ... />

For more information about using style and theme resources in your application, read Styles and Themes. Advanced styling

If you need more advanced styling for the action bar than is available with the properties above, you can include android:actionBarStyle and android:actionBarSplitStyle in your activity's theme. Each of these specifies another style that can define various properties for the action bar, including different backgrounds with android:background, android:backgroundSplit, and android:backgroundStacked. If you override these action bar styles, be sure that you define a parent action bar style such as Widget.Holo.ActionBar.

For example, if you want to change the action bar's background, you can use the following styles:

<?xml version="1.0" encoding="utf-8"?> <resources>

   <style name="CustomActivityTheme" parent="@android:style/Theme.Holo">
       <item name="android:actionBarStyle">@style/MyActionBar</item>
   </style>
   <style name="MyActionBar" parent="@android:style/Widget.Holo.ActionBar">
       <item name="android:background">@drawable/ab_background</item>
       <item name="android:backgroundStacked">@drawable/ab_background</item>
       <item name="android:backgroundSplit">@drawable/ab_split_background</item>
   </style>

</resources>

Action Bar a mida

TABS: http://fizzylogic.nl/2012/03/05/mono-for-android-by-example-the-action-bar/

Recursos

Disseny de la barra d'accions

Recursos:

Android ActionBar style generator

Afegint Navigation Tabs

https://github.com/codepath/android_guides/wiki/ActionBar-Tabs-with-Fragments

TabWidget

TODO: No recomanat

Amb fragments

http://developer.android.com/guide/topics/ui/actionbar.html#Tabs

Amb les Action bar es poden utilitzar pestanyes de navegació (en comptes de la forma antiga que era utilitzar el TabWidget). El sistema adapta les pestanyes per a diferents mides de pantalla, quan hi ha prou espai es posen a la barra d'accions principal, o si no hi ha prou espai es posen a una barra extra (aka stacked action bar). Vegeu les següents imatges;

TODO: 
actionbar.png
actionbar-stacked.png

Per canviar entre Fragments de la nostra aplicació utilitzant les pestanyes, cal realitzar una Fragment transaction cada cop que es selecciona una pestanya. Vegeu Fragments

El layout ha d'incloure un ViewGroup a on es posa cada fragment associat a una pestanya. Cal donar un resource ID al ViewGroup per tal de poder utilitzar-lo al nostre codi de canviar de pestanyes.

NOTA: Si el contingut del tab omplirà tot el layout (excepte l'Action Bar), aleshores no cal ni layout ni cal cridar el mètode setContentView(). En aquest cas es pot posar cada Fragment a l'arrel de de ViewGroup

Un cop es determina a on apareix cada fragment dins del nostre layout, el procediment bàsic per afegir els tabs és:

Vegem un exemple de com implementar ActionBar.TabListener de forma que cada pestanya utilitzi la seva pròpia instància de listener:

public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    /** Constructor used each time a new tab is created.
      * @param activity  The host Activity, used to instantiate the fragment
      * @param tag  The identifier tag for the fragment
      * @param clz  The fragment's Class, used to instantiate the fragment
      */
    public TabListener(Activity activity, String tag, Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    /* The following are each of the ActionBar.TabListener callbacks */

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // Check if the fragment is already initialized
        if (mFragment == null) {
            // If not, instantiate and add it to the activity
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
        } else {
            // If it exists, simply attach it in order to show it
            ft.attach(mFragment);
        }
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        if (mFragment != null) {
            // Detach the fragment, because another one is being attached
            ft.detach(mFragment);
        }
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // User selected the already selected tab. Usually do nothing.
    }
}

És important tenir en compte:

android.R.id.content

Què és un recurs per defecte del sistema que fa referència al root element de la vista, sense necessitat de saber el seu nom actual. Per exemple suposem que el layout de l'activitat és:

 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
 
 </LinearLayout>

Fixeu-vos que no teniu ni id del LinearLayout, què és en aquest cas el root element.

NOTA: vegeu un exemple de com afegir una animació a mida al canviar tabshttp://androidfornewbies.blogspot.com/2012/05/22-actionbar-navigation-with-fragments.html:

 ft.setCustomAnimations(android.R.animator.fade_in, R.animator.animationtest);
 ft.attach(mFragment);

Observeu que el mètodes onTabSelected, onTabUnselected, onTabReselected, només proporcionen el ActionBar.Tab que s'ha seleccionat i un FragmentTransaction per tal de fer la transició entre fragments. No hi ha cap associació predefinida entre els fragments, i per tant es responsabilitat del programador definir aquestes relacions. Es pot fer de diferents maneres, a l'exemple, el constructor de la implementació ActionBar.TabListener força que cada nova pestanya utilitzi el seu propi Listener.

IMPORTANT: No s'ha de cridar commit() del fragment transaction in each of these callbacks—the system calls it for you and it may throw an exception if you call it yourself. You also cannot add these fragment transactions to the back stack

A l'exemple el Listener simplement ajunta ( attach() ) un fragment al layout de l'activitat ( o si no existeix el fragment el crear i l'ajunta) quan la pestanya relativa a aquell fragment s'ha seleccionat, i la desajunta ((detach()) quan se deselecciona la pestanya.

Ara només cal afegir els tabs al Action Bar. Per fer els tabs visibles:

 setNavigationMode(NAVIGATION_MODE_TABS)

per desactivar el títol de l'activitat:

 
 setDisplayShowTitleEnabled(false)

Un exemple:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Notice that setContentView() is not used, because we use the root
    // android.R.id.content as the container for each fragment

    // setup action bar for tabs
    ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    actionBar.setDisplayShowTitleEnabled(false);

    Tab tab = actionBar.newTab()
            .setText(R.string.artist)
            .setTabListener(new TabListener<ArtistFragment>(
                    this, "artist", ArtistFragment.class));
    actionBar.addTab(tab);

    tab = actionBar.newTab()
        .setText(R.string.album)
        .setTabListener(new TabListener<AlbumFragment>(
                this, "album", AlbumFragment.class));
    actionBar.addTab(tab);
}

NOTA: L'exemple mostrat és només una forma de fer-ho. Als samples es poden trobar més formes possibles:

http://arvid-g.de/12/android-4-actionbar-with-tabs-example

IMPORTANT: És important salvar l'estat de cada fragment per tal de mantenir la consistència quan l'usuari va navegant entre fragments i també quan l'aplicació s'atura temporalment, per exemple, al tornar endarrere. Vegeu Fragments f each fragment as necessary, so that when users switch fragments with the tabs and then return to a previous fragment,

A l'hora de salvar l'estat, es pot saber quina és la pestanya actualment seleccionada amb:

getSelectedNavigationIndex()

Que retorna la posició de la pestanya seleccionada.

Cal tenir en compte que el sistema pot arribar a ensenya les tabs com un menú desplegable (drop-down list) per tal d'assegurar-se que caben al Action bar.

També cal tenir en compte la persistència de l'aplicació, per exemple al rotar la pantalla, hem de guardar la pestanya seleccionada:

  @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
    }

El mètode oncreate ara ha de ser:


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Notice that setContentView() is not used, because we use the root
    // android.R.id.content as the container for each fragment

    if (savedInstanceState != null) {
           actionBar.getSelectedNavigationIndex(savedInstanceState.getInt("tab"));
    }
    
    // setup action bar for tabs
    ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    actionBar.setDisplayShowTitleEnabled(false);

    Tab tab = actionBar.newTab()
            .setText(R.string.artist)
            .setTabListener(new TabListener<ArtistFragment>(
                    this, "artist", ArtistFragment.class));
    actionBar.addTab(tab);

    tab = actionBar.newTab()
        .setText(R.string.album)
        .setTabListener(new TabListener<AlbumFragment>(
                this, "album", AlbumFragment.class));
    actionBar.addTab(tab);
}

Recursos:

ActionBarActivity Support

Alternative a Sherlock, molt similar però incorporada a la llibreria Android support ( android-support-v7-appcompat )

public class MainActivity extends ActionBarActivity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       setupTabs();
   }

   private void setupTabs() {
       ActionBar actionBar = getSupportActionBar();
       actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
       actionBar.setDisplayShowTitleEnabled(true);

       Tab tab1 = actionBar
           .newTab()
           .setText("First")
           .setIcon(R.drawable.ic_home)
           .setTabListener(new SupportFragmentTabListener<FirstFragment>(R.id.flContainer, this,
                       "first", FirstFragment.class));

       actionBar.addTab(tab1);
       actionBar.selectTab(tab1);

       Tab tab2 = actionBar
           .newTab()
           .setText("Second")
           .setIcon(R.drawable.ic_mentions)
           .setTabListener(new SupportFragmentTabListener<SecondFragment>(R.id.flContainer, this,
                       "second", SecondFragment.class));
       actionBar.addTab(tab2);
   }

}

Vegeu https://github.com/codepath/android_guides/wiki/ActionBar-Tabs-with-Fragments

Action Bar Sherlock

Consulteu:

https://github.com/codepath/android_guides/wiki/ActionBar-Tabs-with-Fragments

Per veure com treballar amb Action i Fragments / Tabs amb 3 mètodes diferents.

Github:

 https://github.com/codepath/android_guides/wiki/ActionBar-Tabs-with-Fragments

Vegeu:

http://actionbarsherlock.com/

Una llibreria per crear action bars que suporta també tabs.

Recurspos

Navigation pattern. Patró de navegació

En versions anteriors a la 3.0, el sistema operatiu Android es basava en el boto endarrere per navegar per la app. A partir de la versió 3.0, també es pot utilitzar el Up button, que és la icona de l'aplicació a l'Action Bar amb el símbol menor que.

http://developer.android.com/design/patterns/navigation.html

Altres patrons de navegació

Vegeu Drawer Activity

Split action bar

Split action bar és una novetat disponible a Android 4.0 (API level 14) o superior que permet un mode extra d'Action Bar. Quan s'activa aquest opció, una barra separada apareix a la part inferior de la pantalla que mostra totes les accions quan l'activitat es mostra en una pantalla estreta (típicament amb mode portrait)

Per activar aquesta opció afegiu el atribut XML:

uiOptions="splitActionBarWhenNarrow" 

A l'activitat (<activity>) o a l'aplicació (<application> element) al fitxer de manifest.

Utilitzar l'action bar en versions anteriors a 2.0 (backward-compatible)

En aquest cas cal crear a mà el Action Bar a els layouts de la vostra aplicació. Com ajuda hi ha una aplicació d'exemple, aka Action Bar Compatibility sample app:

http://developer.android.com/tools/samples/index.html

Es troba a la carpeta samples del SDK.

Vegeu també

Enllaços externs