Toolbar En Android: Creación De Action Bar En Material Design

De seguro ya sabes que la Action Bar como la conocíamos, está siendo reemplazada por un nuevo componente Android llamado Toolbar.

Las nuevas guías de diseño de Google han introducido el concepto de App Bar.

Una barra que tiene más flexibilidad de transformación y personalización que hace parte del checklist de diseño de Material Design:

Material Design: Uso De La Toolbar En Checklist De Diseño

Así que si deseas crear aplicaciones para Android 5 en adelante es necesario que aprendas a usarla.

Para ello he preparado este tutorial donde crearás una aplicación Android basada en una Toolbar.

Adicionalmente verás cómo extender su comportamiento  con los nuevos elementos de la librería de soporte para diseño, como lo son el CoordinatorLayout, AppBarLayout y CollapsingToolbarLayout.

Descargar Proyecto Android Studio De “Citas Peligrosas”

Si deseas ver el resultado final que obtendrás al final de seguir los pasos de este tutorial, entonces observa el siguiente video:

Para desbloquear el link de descargar del código completo, sigue estas instrucciones:

¿Cómo Añadir La Toolbar En Android?

Debido a que la Toolbar reemplaza a la antigua Action Bar, debes deshabilitarla con el estilo Theme.AppCompat.NoActionBar ó añadiendo los atributos windowActionBar y windowNoTitle con los siguientes valores:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Habilitar la Toolbar -->
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>

    <!--...-->
</style>

Luego de eso implementarla es muy fácil. Solo debes añadir una etiqueta <android.support.v7.widget.Toolbar>  en tus layouts como se hace con los widgets normales.

Android: Ejemplo De Toolbar Como Action Bar

Esta convención otorga todo el poder de la action bar al desarrollar Android, ya que el método antiguo solo permitía la personalización a través de los temas y estilos.

<!-- Toolbar -->
<android.support.v7.widget.Toolbar xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

Algunos puntos a considerar:

Material Design: Toolbar Flexible Más Toolbar En CardView

  • Los action buttons de la Toolbar se inflan a través de un archivo de menú como siempre has hecho.
  • Los eventos se controlan igualmente con el método onOptionsItemSelected().
  • Debes encontrar la instancia de la Toolbar con findViewById() y luego setearla a la actividad con setSupportActionBar() para ponerla en funcionamiento.

CoordinatorLayout: Crear Interacciones Entre Views

La librería de soporte para el diseño de Android nos entrega el CoordinatorLayout para gestionar interaccione entre sus elementos hijos.

¿Qué tipos de interacciones?

Movimiento, animación y scrolling. Sobre todo nos da las herramientas para replicar las técnicas de scrolling en Material Design.

En este tutorial lo usaremos para crear interacciones entre la App Bar y views con scrolling. Sin embargo pueden usarse para otras relaciones.

AppBarLayout: Aumentando Las Capacidades De La Action Bar

Como se dijo al inicio, la App Bar es una expansión del concepto de la action bar. Aunque la Toolbar representa el pequeño segmento rectangular al que estamos acostumbrados, la App Bar (representada con la clase AppBarLayout) es un contenedor con más posibilidades de personalización.

Esta permite dividir los comportamientos de la action bar para independizar las acciones.

Incluso permite añadir efectos de scrolling en conjunto con el Coordinator Layout.

Por ejemplo…Ejemplo De Standard Toolbar En Android Con Scrolling

Si deseas esconder la Toolbar cuando el usuario desplaza un RecyclerView, debes envolver ambos elementos con un coordinator como se ve en el código de abajo.

<android.support.design.widget.CoordinatorLayout 
    ...>

    <!--Objeto Con Scroll -->
    <android.support.v7.widget.RecyclerView
        ...
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <!-- App Bar -->
    <android.support.design.widget.AppBarLayout
        ...>

        <!-- Toolbar -->
        <android.support.v7.widget.Toolbar 
            ...
            app:layout_scrollFlags="scroll|enterAlways" />

    </android.support.design.widget.AppBarLayout>


</android.support.design.widget.CoordinatorLayout>

Para ello debes tener en cuenta lo siguiente:

  • AppBarLayout siempre debe envolver a la Toolbar y los demás componentes pertenecientes a ella (como pestañas, imágenes, etc).
  • El CoordinatorLayout debe envolver directamente a los objetos que desees relacionar mediante una acción.
  • Desaparecer la App Bar por scrolling requiere que haya un objeto con scroll marcado con el atributo app:layout_behavior="@string/appbar_scrolling_view_behavior". Este debe declararse por encima de la App Bar.
  • La forma en que se afectan los hijos de App Bar se determina en app:layout_scrollFlags.

Las banderas de scroll controlan el tipo de comportamiento con que desaparece la Toolbar:

  • scroll: indica que un view desaparecerá al desplazar el contenido.
  • enterAlways:vuelve visible al view ante cualquier signo de scrolling.
  • enterAlwaysCollapsed: vuelve visible el view solo si se mantiene el scroll en la parte superior del contenido.
  • exitUntilCollapsed: desaparece el view hasta que sus dimensiones superen la altura mínima.

CollapsingToolbarLayout: Espacio Flexible De La App Bar

La App Bar es un elemento flexible capaz de aumentar o reducir su tamaño para desplegar mejor experiencia de usuario dependiendo de las interacciones que se ejerzan sobre ella.

Para implementar esta característica se usa el CollapsingToolbarLayout. Un layout especial que envuelve a la Toolbar para controlar las reacciones de expansión y contracción de los elementos que se encuentran dentro de un AppBarLayout.

Con reacciones me refiero a la variación de sus dimensiones y las desapariciones de la escena si es necesario.

Collapsing Toolbar: Ejemplo En Android Con Material Design

Para crear una App Bar con que contraiga, solo envuelves la Toolbar de la siguiente forma:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">


    <!-- Objeto con Scroll -->
    <android.support.v4.widget.NestedScrollView
        ...
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <!--Contenido desplazable -->

    </android.support.v4.widget.NestedScrollView>

    <!-- App Bar -->
    <android.support.design.widget.AppBarLayout
        ...>

        <!-- Collapser -->
        <android.support.design.widget.CollapsingToolbarLayout
            ...
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <!-- Toolbar -->
            <android.support.v7.widget.Toolbar 
                ...
                app:layout_collapseMode="pin"/>

        </android.support.design.widget.CollapsingToolbarLayout>


    </android.support.design.widget.AppBarLayout>


</android.support.design.widget.CoordinatorLayout>

El código anterior contrae y expande la AppBar al momento de usar el scrolling. Para comprender el funcionamiento recuerda las siguientes instrucciones:

  • El CollapsingToolbarLayout debe envolver directamente a la Toolbar.
  • La Toolbar puede sobrevivir a la contracción del contenido a través del atributo app:layout_scrollMode="pin". Los demás elementos desaparecerán.
  • Puedes animar el titulo de la Toolbar añadiéndolo al CollapsingToolbarLayout con setTitle().
  • Al reducir un view puedes usar un efecto Parallax (es necesario aplicar el atributo app:layout_collapseMode="parallax") para difuminar su background con el color indicado en app:contentScrim .

Si quieres ahorrar tiempo implementando el Material Design en tus app Android, te recomiendo la plantilla Material Design App de Codecanyon

Crear Aplicación Android Con Toolbar

Paso #1: En Android Studio, crea un nuevo proyecto yendo a File > New Project. Llámalo “Citas Peligrosas”. Selecciona Blank Activity y confirma.

Paso #2: A continuación crea una nueva clase llamada DetailActivity.java. Esta actividad contendrá el detalle para cada ítem del Recycler View que se usará para mostrar la lista de chicas con las que queremos tener citas.

Paso #3: Agrega las dependencias del código de abajo al archivo build.gradle. Verás tres nuevas librerías: La librería de diseño de soporte antes mencionada; la librería Circle Image View que permite crear Image Views circulares y la librería Glide que nos permitirá cargar en segundo plano las imágenes.

build.gradle

dependencies {
    ...
    compile 'com.android.support:appcompat-v7:22.2.0'
    compile 'com.android.support:design:22.2.0'
    compile 'com.android.support:recyclerview-v7:22.2.0'
    compile 'com.android.support:cardview-v7:22.2.0'
    compile 'com.github.bumptech.glide:glide:3.6.0'
    compile 'de.hdodenhof:circleimageview:1.3.0'
}

Paso #4: Ve a res/values/strings.xml y agrega las siguientes cadenas:

strings.xml

<resources>
    <string name="app_name">Citas Peligrosas</string>

    <string name="action_settings">Settings</string>
    <string name="action_add">Añadir</string>
    <string name="action_favorite">Marcar Favorito</string>

    <string name="title_activity_detail">DetailActivity</string>

    <string name="girl_ipsum">
        Morbi posuere lorem nec elit dapibus, vitae accumsan mauris pellentesque.
        Vestibulum a lobortis mi. Vestibulum lacinia molestie semper. Pellentesque
        ultrices arcu lacus, interdum mollis nibh convallis ut. Aliquam sagittis
        sem a lacus gravida, eu accumsan purus volutpat. Donec tempus, est id
        tristique consectetur, lacus ligula dignissim turpis, cursus commodo turpis
        libero in purus. Phasellus tempus gravida tempor.
    </string>
    <string name="action_search">Buscar</string>
</resources>

Paso #5: Crea un nuevo archivo colors.xml en res/values y agrega los siguientes colores para el tema con Material Design:

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="darkPrimaryColor">#D32F2F</color>
    <color name="primaryColor">#F44336</color>
    <color name="accentColor">#448AFF</color>
</resources>

Paso #6: Lo siguiente es ir a res/values/dimens.xml y añadir las dimensiones de abajo.

dimens.xml

<resources>

    <dimen name="headerbar_elevation">4dp</dimen>
    <dimen name="card_margin">16dp</dimen>
    <dimen name="size_fab">56dp</dimen>
    <dimen name="fab_margin">16dp</dimen>
    <dimen name="avatar_size">40dp</dimen>

</resources>

Paso #7: Ahora crearemos el POJO de los objetos de la lista. Añade una nueva clase llamada Girl.java con el código de abajo. Este es el modelo de datos para los elementos del RecyclerView.

Girl.java

import java.util.Random;

/**
 * POJO de las chicas
 */
public class Girl {

    private String name;
    private int idDrawable;

    public Girl(String name, int idDrawable) {
        this.name = name;
        this.idDrawable = idDrawable;
    }

    public Girl(String name) {
        this.name = name;
        this.idDrawable = getRandomGirlDrawable();
    }

    public String getName() {
        return name;
    }

    public int getIdDrawable() {
        return idDrawable;
    }

    /**
     * Asigna un drawable en forma aleatoria
     *
     * @return id del drawable
     */
    private int getRandomGirlDrawable() {
        Random rnd = new Random();
        switch (rnd.nextInt(8)) {
            default:
            case 0:
                return R.drawable.girl1;
            case 1:
                return R.drawable.girl2;
            case 2:
                return R.drawable.girl3;
            case 3:
                return R.drawable.girl4;
            case 4:
                return R.drawable.girl5;
            case 5:
                return R.drawable.girl6;
            case 6:
                return R.drawable.girl7;
            case 7:
                return R.drawable.girl8;
        }
    }
}

Paso #8: Descarga y extrae las imágenes de este archivo. Luego pégalas en res/drawable. Estas permitirán crear las miniaturas y el detalle de cada ítem.

Paso #9: Añade otra clase con el nombre de Girls.java para representar una estructura de datos de prueba. Con ella se poblará el adaptador.

Los objetos que se usarán tendrán datos aleatorios. Por lo que verás un método llamado randomList() para cumplir esta función.

Girls.java

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Envoltura para generar una lista de ejemplo
 */
public class Girls {

    public static final String[] girlsNamesDummy = {
            "Catherine", "Evelyn", "Phyllis", "Beverly", "Michelle",
            "Denise", "Virginia", "Ruth", "Barbara", "Amanda", "Anna",
            "Catherine", "Melissa", "Sandra", "Julia", "Paula", "Kimberly",
            "Diane", "Betty", "Sharon", "Ruby", "Barbara", "Ann", "Phyllis",
            "Linda", "Marie", "Deborah", "Sara", "Gloria", "Karen", "Patricia",
            "Donna", "Catherine", "Louise", "Catherine", "Joyce", "Katherine",
            "Janice", "Cheryl", "Lisa", "Andrea", "Elizabeth", "Nicole",
            "Cynthia", "Angela", "Donna", "Deborah", "Sandra", "Cheryl", "Jane"
    };

    /**
     * Genera una lista de objetos {@link Girl} con un tamaño determinado
     *
     * @param count Tamaño
     * @return Lista aleatoria
     */
    public static List<Girl> randomList(int count) {
        Random random = new Random();
        List<Girl> items = new ArrayList<>();

        // Restricción de tamaño
        count = Math.min(count, girlsNamesDummy.length);

        while (items.size() < count) {
            items.add(new Girl(girlsNamesDummy[random.nextInt(girlsNamesDummy.length)]));
        }

        return new ArrayList<>(items);
    }
}

Paso #10: Modifica el layout de DetailActivity.java con la definición XML de abajo. Básicamente este diseño se compone de:

  • Un CoordinatorLayout para crear una Collapsing Toolbar.
  • Una imagen representativa dentro de la App Bar.
  • Cardviews para agregar secciones hipotéticas como: Perfil, Amigos e Intereses.
  • Un Floating Action Button relacionado a la app bar para un posible inicio de chat. La clase FloatingActionButton también hace parte de la librería de soporte.

Superimportante resaltar que el coordinator proporciona dos atributos para que el FAB (en general para todos los elementos flotantes)  flote con referencia a un view hermano.

  • layout_anchor: Es el view al que será anclado el FAB.
  • layout_anchorGravity: La ubicación del elemento. Puedes usar banderas como bottom, top, end, etc.

activity_detail.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">


    <!-- Objeto con Scroll -->
    <android.support.v4.widget.NestedScrollView
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/app_bar"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:paddingTop="24dp">

            <!-- Card Perfil -->
            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/card_margin">

                <LinearLayout
                    style="@style/Widget.CardContent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">
                    <!--Etiqueta Perfil -->
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Perfil"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title" />
                    <!--Texto de ejemplo-->
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/girl_ipsum" />

                </LinearLayout>

            </android.support.v7.widget.CardView>

            <!-- Card Amigos -->
            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="@dimen/card_margin"
                android:layout_marginLeft="@dimen/card_margin"
                android:layout_marginRight="@dimen/card_margin">

                <LinearLayout
                    style="@style/Widget.CardContent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <!-- Etiqueta Amigos -->
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Amigos(450)"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title" />
                    <!-- Texto de ejemplo -->
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/girl_ipsum" />

                </LinearLayout>

            </android.support.v7.widget.CardView>

            <!-- Card Intereses -->
            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="@dimen/card_margin"
                android:layout_marginLeft="@dimen/card_margin"
                android:layout_marginRight="@dimen/card_margin">

                <LinearLayout
                    style="@style/Widget.CardContent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <!-- Etiqueta Intereses -->
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Intereses"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                    <!-- Texto de ejemplo -->
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/girl_ipsum" />

                </LinearLayout>

            </android.support.v7.widget.CardView>

        </LinearLayout>

    </android.support.v4.widget.NestedScrollView>

    <!-- App Bar -->
    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="256dp"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <!-- Collapser -->
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapser"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <!-- Imagen del detalle -->
            <ImageView
                android:id="@+id/image_paralax"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax" />

            <!-- Toolbar -->
            <android.support.v7.widget.Toolbar xmlns:app="http://schemas.android.com/apk/res-auto"
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@android:color/transparent"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:theme="@style/CustomActionBar"

                />

        </android.support.design.widget.CollapsingToolbarLayout>


    </android.support.design.widget.AppBarLayout>

    <!-- FAB -->
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="@dimen/size_fab"
        android:layout_height="@dimen/size_fab"
        android:layout_margin="@dimen/fab_margin"
        android:src="@mipmap/ic_chat"
        app:borderWidth="0dp"
        app:elevation="@dimen/fab_elevation"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|right|end" />


</android.support.design.widget.CoordinatorLayout>

Paso #11: Descarga los siguientes iconos para la Toolbar de la actividad de detalle. Al extraer el contenido, pega las carpetas en res.

Paso #12: Ahora debes actualizar el menú de tu actividad de detalle. Ve a res/menu/detail.xml y pega el código de abajo. Solo tendremos tres action buttons para añadir, agregar a favoritos y los ajustes:

detail.xml

<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="com.herprogramacion.toolbarapp.DetailActivity">
    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="@string/action_settings"
        app:showAsAction="never" />
    <item
        android:id="@+id/action_add"
        android:icon="@mipmap/ic_person_add"
        android:orderInCategory="1"
        android:title="@string/action_add"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_favorite"
        android:icon="@mipmap/ic_favorite"
        android:orderInCategory="2"
        android:title="@string/action_favorite"
        app:showAsAction="ifRoom" />
</menu>

Paso #13: Abre DetailActivity.java y agrega el código de abajo.  El objetivo es cargar los datos de la chica que vienen desde el recycler  y setearlos en cada view.

Si te fijas, en las acciones de los action buttons mostramos mensajes con la llamada del método showSnackBar().  Su función crear un nuevo elemento de la librería de diseño llamado SnackBar con la cadena especificada. Este componente es muy parecido a los Toasts, solo que permiten añadir una acción en su contenido.

DetailActivity.java

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;

import com.bumptech.glide.Glide;

public class DetailActivity extends AppCompatActivity {


    private static final String EXTRA_NAME = "com.herprogramacion.toolbarapp.name";
    private static final String EXTRA_DRAWABLE = "com.herprogramacion.toolbarapp.drawable";

    /**
     * Inicia una nueva instancia de la actividad
     *
     * @param activity Contexto desde donde se lanzará
     * @param title    Item a procesar
     */
    public static void createInstance(Activity activity, Girl title) {
        Intent intent = getLaunchIntent(activity, title);
        activity.startActivity(intent);
    }

    /**
     * Construye un Intent a partir del contexto y la actividad
     * de detalle.
     *
     * @param context Contexto donde se inicia
     * @param girl    Identificador de la chica
     * @return Intent listo para usar
     */
    public static Intent getLaunchIntent(Context context, Girl girl) {
        Intent intent = new Intent(context, DetailActivity.class);
        intent.putExtra(EXTRA_NAME, girl.getName());
        intent.putExtra(EXTRA_DRAWABLE, girl.getIdDrawable());
        return intent;
    }

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

        setToolbar();// Añadir action bar
        if (getSupportActionBar() != null) // Habilitar up button
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        Intent i = getIntent();
        String name = i.getStringExtra(EXTRA_NAME);
        int idDrawable = i.getIntExtra(EXTRA_DRAWABLE, -1);

        CollapsingToolbarLayout collapser =
                (CollapsingToolbarLayout) findViewById(R.id.collapser);
        collapser.setTitle(name); // Cambiar título

        loadImageParallax(idDrawable);// Cargar Imagen

        // Setear escucha al FAB
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        showSnackBar("Opción de Chatear");
                    }
                }
        );


    }

    private void setToolbar() {
        // Añadir la Toolbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

    /**
     * Se carga una imagen aleatoria para el detalle
     */
    private void loadImageParallax(int id) {
        ImageView image = (ImageView) findViewById(R.id.image_paralax);
        // Usando Glide para la carga asíncrona
        Glide.with(this)
                .load(id)
                .centerCrop()
                .into(image);
    }

    /**
     * Proyecta una {@link Snackbar} con el string usado
     *
     * @param msg Mensaje
     */
    private void showSnackBar(String msg) {
        Snackbar
                .make(findViewById(R.id.coordinator), msg, Snackbar.LENGTH_LONG)
                .show();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.detail, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        switch (id) {
            case R.id.action_settings:
                showSnackBar("Se abren los ajustes");
                return true;
            case R.id.action_add:
                showSnackBar("Añadir a contactos");
                return true;
            case R.id.action_favorite:
                showSnackBar("Añadir a favoritos");
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }


    }
}

Paso #14: Lo siguiente es crear nuestro layout para los ítems de la lista. Dirígete a res/layout y crea un nuevo layout llamado list_item.xml. La idea es representar una sola línea de texto con un avatar.

list_item.xml

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:paddingBottom="8dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="8dp">

    <!-- Image circular de la librería externa -->
    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/avatar"
        android:layout_width="@dimen/avatar_size"
        android:layout_height="@dimen/avatar_size"
        android:layout_marginRight="16dp" />

    <!-- Nombre de la chica -->
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/list_item_textview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?attr/textAppearanceListItem" />

</LinearLayout>

Paso #15: Crea una nueva clase llamada SimpleAdapter.java. Esta clase es un RecyclerView.Adapter personalizado que inflará el nombre y avatar de cada chica desde list_item.xml.

SimpleAdapter.java

import android.app.Activity;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.util.List;

public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.SimpleViewHolder>
        implements ItemClickListener {
    private final Context context;
    private List<Girl> items;

    public static class SimpleViewHolder extends RecyclerView.ViewHolder
            implements View.OnClickListener {
        // Campos respectivos de un item
        public TextView nombre;
        public ImageView avatar;
        public ItemClickListener listener;

        public SimpleViewHolder(View v, ItemClickListener listener) {
            super(v);

            nombre = (TextView) v.findViewById(R.id.list_item_textview);
            avatar = (ImageView) v.findViewById(R.id.avatar);
            this.listener = listener;
            v.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            listener.onItemClick(v, getAdapterPosition());
        }
    }

    public SimpleAdapter(Context context, List<Girl> items) {
        this.context = context;
        this.items = items;
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    @Override
    public SimpleViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.list_item, viewGroup, false);
        return new SimpleViewHolder(v, this);
    }

    @Override
    public void onBindViewHolder(SimpleViewHolder viewHolder, int i) {
        Girl currentItem = items.get(i);
        viewHolder.nombre.setText(currentItem.getName());
        Glide.with(viewHolder.avatar.getContext())
                .load(currentItem.getIdDrawable())
                .centerCrop()
                .into(viewHolder.avatar);
    }

    /**
     * Sobrescritura del método de la interfaz {@link ItemClickListener}
     *
     * @param view     item actual
     * @param position posición del item actual
     */
    @Override
    public void onItemClick(View view, int position) {
        DetailActivity.createInstance(
                (Activity) context, items.get(position));
    }


}


interface ItemClickListener {
    void onItemClick(View view, int position);
}

Paso #16: Ahora es el turno del layout de MainActivity.java. Ve a res/layout/activity_main.xml y añade la siguiente definición. Habrá una App Bar con espacio flexible que se reducirá al desplazar el recycler view.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.CoordinatorLayout xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/coordinator"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!--Objeto Con Scroll -->
        <android.support.v7.widget.RecyclerView
            android:id="@+id/reciclador"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/coordinator"
            android:padding="3dp"
            android:scrollbars="vertical"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

        <!-- App Bar -->
        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <!-- Toolbar -->
            <android.support.v7.widget.Toolbar xmlns:app="http://schemas.android.com/apk/res-auto"
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:layout_scrollFlags="scroll|enterAlways"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

        </android.support.design.widget.AppBarLayout>


    </android.support.design.widget.CoordinatorLayout>
</RelativeLayout>

Paso #17: Ya para finalizar, abre MainActivity.java y realiza los siguientes cambios:

  • Añade la Toolbar (puedes crear un método llamado setToolbar() para ello).
  • Quita el título de la app bar y setealo en el CollapsingToolbarLayout.
  • Crea el adaptador y setealo en el RecyclerView.

MainActivity.java

import android.os.Bundle;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {


    private RecyclerView recycler;
    private LinearLayoutManager lManager;
    private CollapsingToolbarLayout collapser;

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

        setToolbar();// Añadir la Toolbar

        SimpleAdapter adaptador = new SimpleAdapter(this, Girls.randomList(30));

        // Obtener el Recycler
        recycler = (RecyclerView) findViewById(R.id.reciclador);
        recycler.setHasFixedSize(true);

        // Usar un administrador para LinearLayout
        lManager = new LinearLayoutManager(this);
        recycler.setLayoutManager(lManager);

        // Crear un nuevo adaptador

        recycler.setAdapter(adaptador);


    }

    private void setToolbar() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id) {
            case R.id.action_search:de
                showSnackBar("Comenzar a buscar...");
                return true;
            case R.id.action_settings:
                showSnackBar("Se abren los ajustes");
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * Proyecta una {@link Snackbar} con el string usado
     *
     * @param msg Mensaje
     */
    private void showSnackBar(String msg) {
        Snackbar
                .make(findViewById(R.id.coordinator), msg, Snackbar.LENGTH_LONG)
                .show();
    }
}

Paso #18: Ejecuta la aplicación en Android Studio:

Toolbar En Android: CoordinatorLayout y CollapsingToolbarLayout

Conclusión

¿Pudiste implementar la Toolbar en Android?

Bien, en este tutorial has visto los pasos necesarios para crear una interfaz simple pero visualmente atractiva.

La librería de soporte de diseño de Google es el gran avance que necesitábamos para comenzar con el Material Design de forma robusta. No obstante aún tiene varios bugs, por lo que podemos esperar que mejore con el tiempo.

Recuerda actualizar el SDK de Android para estar al tanto de las mejoras y obtener el funcionamiento completo de las librerías de soporte.

Ahora el paso a seguir es comprender como crear un Navigation Drawer en Android con el nuevo widget para Material Design.