44 - Componente ActionBar (Básica)


A partir de la versión 4.0 se introduce para el desarrollo de aplicaciones para celulares Android la componente ActionBar.
La componente ActionBar es la barra que aparece en la parte superior de gran cantidad de aplicaciones. Esta componente busca estandarizar entre distintas aplicaciones desarrolladas para Android la ubicación de botones de acciones, menú de opciones etc.

Ahora cuando creamos con el Android Studio una aplicación mínima con la opción "Blank Activity" se genera por defecto el ActionBar.

La interfaz mínima del ActionBar es:

ActionBar

En el lado izquierdo aparece el nombre de la aplicación y del lado derecha aparece un botón que al ser presionado nos muestra un menú desplegable:

ActionBar

Problema:

Confeccionar una aplicación que muestre en el ActionBar el título "Este mundo" y luego tres opciones en el menú desplegable del ActionBar.

La interfaz del ActionBar y el menú desplegable debe ser similar a:

ActionBar

Veamos los pasos que debemos dar para obtener este resultado:

  1. El título del ActionBar lo debemos modificar abriendo el archivo strings que se encuentra en la carpeta res/values y su contenido por defecto al crear el proyecto es:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <string name="app_name">Proyecto047</string>
        <string name="hello_world">Hello world!</string>
        <string name="action_settings">Settings</string>
    
    </resources>
    

    Podemos cambiar el contenido de la constante "app_name":

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <string name="app_name">Este mundo</string>
        <string name="hello_world">Hello world!</string>
        <string name="action_settings">Settings</string>
    
    </resources>
    

    Recordemos que este archivo de recursos se utiliza para agrupar todos los mensajes que aparecen en pantalla y facilitar la implementación de aplicaciones para varios idiomas independiente de los algoritmos de la misma.

    En este archivo hemos creado un string llamado "app_name" con el valor "Este mundo".
    Luego este string se asocia con el título de la aplicación con la propiedad label en el archivo AndroidManifest.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="ar.com.tutorialesya.proyecto047" >
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name=".MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    Desde el Editor del Android Studio cuando vemos el archivo AndroidManifest.xml nos sustituye visualmente las constantes por los valores de las constantes para ver que realmente se almacena:

    ActionBar AndroidManifest.xml

    Pero si posicionamos el mouse sobre el valor veremos que está definida una constante con la sintaxis @string/[nombre de constante]:

    ActionBar AndroidManifest.xml

    Y si hacemos clic veremos el contenido real del valor con el que se inicializa la propiedad.

    En este archivo XML ya está inicializada la propiedad label de la marca application con el valor definido en el archivo xml (como vemos acá hacemos referencia al string app_name):

            android:label="@string/app_name"
    
  2. Ahora tenemos que definir las opciones de nuestro menú desplegable, para esto abrimos el archivo menu_main.xml de la carpeta res/menu y definimos las tres opciones que contendrá nuestro menú y eliminamos la que define por defecto cuando creamos un proyecto desde Android Studio:

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
    
        <item
            android:id="@+id/opcion1"
            app:showAsAction="never"
            android:title="Opción 1"/>
        <item
            android:id="@+id/opcion2"
            app:showAsAction="never"
            android:title="Opción 2"/>
        <item
            android:id="@+id/opcion3"
            app:showAsAction="never"
            android:title="Opción 3"/>
    </menu>
    

    Como necesitamos tres opciones definimos tres marcas item e inicialzamos las propiedades id, showAsAction (indicando con el valor never que deben aparecer en el menú desplegable) y mediante la propiedad title el texto que queremos que muestre (como vemos al asignar directamente el texto a la propiedad title hay que tener en cuenta que la mejor práctica es definir el mensaje en el archivo strings.xml y acá hacer referencia a dicho string mediante un @string/[constante], por el momento para hacerlo más corto y directo al problema lo hacemos con el texto a mostrar directamente)

  3. La funcionalidad de nuestro programa será mostrar un Toast cuando se seleccione alguno de las opciones del menú. El código java de la clase debe ser:

    package ar.com.tutorialesya.proyecto047;
    
    import android.support.v7.app.ActionBarActivity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.Toast;
    
    
    public class MainActivity extends ActionBarActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
    
            //noinspection SimplifiableIfStatement
    
    
    //        Debemos borrar este if que creó el Android Studio con la opción por defecto.
    //        if (id == R.id.action_settings) {
    //            return true;
    //        }
    
            if (id==R.id.opcion1) {
                Toast.makeText(this,"Se seleccionó la primer opción",Toast.LENGTH_LONG).show();
            }
    
            if (id==R.id.opcion2) {
                Toast.makeText(this,"Se seleccionó la segunda opción",Toast.LENGTH_LONG).show();
            }
    
            if (id==R.id.opcion3) {
                Toast.makeText(this,"Se seleccionó la tercer opción",Toast.LENGTH_LONG).show();
            }
    
            return super.onOptionsItemSelected(item);
        }
    }
    

    Como podemos observar hemos modificado el método onOptionsItemSelected que se ejecuta cada vez que el usuario selecciona una opción del menú:

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
    
            //noinspection SimplifiableIfStatement
    
    
    //        Debemos borrar este if que creó el Android Studio con la opción por defecto.
    //        if (id == R.id.action_settings) {
    //            return true;
    //        }
    
            if (id==R.id.opcion1) {
                Toast.makeText(this,"Se seleccionó la primer opción",Toast.LENGTH_LONG).show();
            }
    
            if (id==R.id.opcion2) {
                Toast.makeText(this,"Se seleccionó la segunda opción",Toast.LENGTH_LONG).show();
            }
    
            if (id==R.id.opcion3) {
                Toast.makeText(this,"Se seleccionó la tercer opción",Toast.LENGTH_LONG).show();
            }
    
            return super.onOptionsItemSelected(item);
        }
    }

    Podemos ahora entender el objetivo del método onCreateOptionsMenu que se genera al crear el proyecto. En el mismo se procesa el archivo menu_main.xml donde definimos el menú de opciones:

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
    

Hemos borrado las líneas:

        Debemos borrar este if que creó el Android Studio con la opción por defecto.
        if (id == R.id.action_settings) {
            return true;
        }

Ya que es la opción que crea por defecto el Android Studio en nuestro esquelelo básico del proyecto.

Este proyecto lo puede descargar en un zip desde este enlace: proyecto047.zip

Problema:

Confeccionar el mismo problema del ActionBar con el menú de opciones pero utilizando constantes para cada opción del menú y también constantes para los tres mensajes que aparecen cuando se seleccionan cada una de las opciones.

Creemos un proyecto llamado "Proyecto048" y creemos primero el archivo strings.xml con todas las constantes necesarias de nuestro programa:

strings.xml

Es decir modificamos el valor de app_name y creamos seis constantes más, tres para las etiquetas de las opciones del menú y tres para los mensajes que deben aparecer cuando se presionen las opciones.

El archivo menu_main ahora queda codificado así:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">

    <item
        android:id="@+id/opcion1"
        app:showAsAction="never"
        android:title="@string/opcion_menu1"/>
    <item
        android:id="@+id/opcion2"
        app:showAsAction="never"
        android:title="@string/opcion_menu2"/>
    <item
        android:id="@+id/opcion3"
        app:showAsAction="never"
        android:title="@string/opcion_menu3"/>
</menu>

Es decir hemos inicializado cada propiedad title de los item con los nombres de las constantes que creamos en el archivo strings.xml.

Finalmente el código fuente de la aplicación sufre los siguientes cambios para utilizar las constantes del archivo strings.xml cuando se deben mostrar los mensajes:

package ar.com.tutorialesya.proyecto048;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;


public class MainActivity extends ActionBarActivity {

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


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        if (id==R.id.opcion1) {
            Toast.makeText(this,getString(R.string.mensaje_1),Toast.LENGTH_LONG).show();
        }

        if (id==R.id.opcion2) {
            Toast.makeText(this,getString(R.string.mensaje_2),Toast.LENGTH_LONG).show();
        }

        if (id==R.id.opcion3) {
            Toast.makeText(this,getString(R.string.mensaje_3),Toast.LENGTH_LONG).show();
        }


        return super.onOptionsItemSelected(item);
    }
}

Lo nuevo aquí es ver que antes para mostrar el mensaje directamente en el código Java hacíamos:

        if (id==R.id.opcion1) {
            Toast.makeText(this,"Se seleccionó la primer opción",Toast.LENGTH_LONG).show();
        }

Ahora vemos si queremos extraer el dato de la constante que se encuentra en el archivo strings.xml lo debemos hacer llamando al método getString y pasando la referencia al nombre de la constante que se encuentra en la clase R y dentro de esta en una clase interna llamada string:

        if (id==R.id.opcion1) {
            Toast.makeText(this,getString(R.string.mensaje_1),Toast.LENGTH_LONG).show();
        }

Retornar