AppBarLayout & Toolbar (Android)

TEORÍA

La AppBarLayout es la típica barra superior de una aplicación Android en la que habitualmente se muestra el nombre de la app, el botón de opciones (representado habitualmente por tres puntos dispuestos verticalmente), el botón para abrir el menú de navegación, etc.

Dentro de este Layout se puede añadir una View Toolbar para que se incluya el botón de opciones (y sus correspondientes botones que se deseen estén visibles en la AppBarLayout siempre que el ancho de la pantalla así lo permita); las opciones de dicho botón se almacenan en un menú (res/menu) y se le asigna a la toolbar programáticamente en el evento de la Activity «onCreateOptionsMenu«.

PRÁCTICA

Estructura XML

La estructura que debe seguirse para añadir una AppBar al layout es la siguiente (el primer LinearLayout que aparece es el nodo raíz):

<!-- Por simplificar se ha reducido el nombre de las etiquetas, pero sus 
nombres originales para retrocompatibilidad de versiones de Android son: -->
<!-- AppBarLayout = android.support.design.widget.AppBarLayout -->
<!-- Toolbar = android.support.v7.widget.Toolbar -->

<LinearLayout ...> <!-- Root -->

  <AppBarLayout 
     ...
    android:layout_height="?attr/actionBarSize"
    android:theme="@style/AppTheme.AppBarOverlay">

        <Toolbar ... />

    </AppBarLayout>

    <!-- Resto de la activity -->
    <LinearLayout 
    	...
      app:layout_behavior="android.support.design.widget.AppBarLayout$ScrollingViewBehavior">
    </LinearLayout>

</LinearLayout>

NOTA: Donde pone LinearLayout quiere decir que no requiere de un Layout especial, podría ser LinearLayout, ConstraitLayout, etc.

Manipulación dinámica (código)

Inicialización

Primero se debe añadir el botón del menú de opciones:

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

Y luego indicarle qué menú va a utilizar (las opciones del menú se almacenarán en «res/menu«). En este caso se le añade las opciones de «res/menu/miMenu«,

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.miMenu, menu);
    return true;
}
Modificar título

Se puede modificar el título que aparece en la toolbar:

toolbar.setTitle("blabla");
Evento: pulsar el botón de opciones

Evento lanzado cuando se pulsa en el botón de opciones (antes de que llegue a mostrarse); útil, por ejemplo, para desactivar opciones del menú según el contexto.

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    //Se accede al ítem usando el id que 
    //tiene dentro del menú directamente
    MenuItem opcion1 = menu.findItem(R.id.opcion_1);
    if(/*Condición*/){
        opcion1.setEnabled(true);
    }
    return true;
}
Evento: pulsar un ítem de las opciones

Evento lanzado cuando se pulsa en cada uno de los ítems del menú de opciones

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == R.id.opcion_1) {
        //...
        return true;
    }
    else if (id == R.id.opcion_2) {
        //...
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Añadir AppBar con un theme

Hay que tener en cuenta que la Activity puede tener una AppBar estática si se usa un theme (tema) en el manifiesto que ya incluya AppBar.

Si se utiliza una AppBar por tema, no se le podrá añadir un nodo Toolbar ya que no va a existir el layout AppBarLayout (porque el propio theme de la Activity traerá su propia AppBar), así que una AppBar estática prescindirá de botones de acción (debido a que no tendremos un nodo Toolbar al que referenciar para añadirle los botones del menú).

También hay que destacar que, si el propio theme de la Activity tiene ya una AppBar, añadir otra en el Layout provocará que se inserten dos barras seguidas.

Para indicar explícitamente que no se desea una AppBar por defecto en la Activity hay que utilizar un theme que no incluya AppBar (por ejemplo, el «AppTheme.NoActionBar»).

<manifest ...>
  <!-- ... -->
  <activity 
    android:name=".MiActivity"
      android:theme="@style/AppTheme.NoActionBar"/>
  <!-- ... -->
</manifest>

En otro caso, si deseamos usar la AppBar por theme, se puede indicar el título de la misma en el atributo «label» de la Activity en el manifiesto.

<manifest ...>
  <!-- ... -->
  <activity 
    android:name=".MiActivity"
      android:label="Título de mi Activity"/>
  <!-- ... -->
</manifest>