Comunidad de diseño web y desarrollo en internet online

Material Design en versiones Anteriores a Lollipop


Es cierto que Lollipop aun no llega a todos los dispositivos, pero desde su antes nombre L ha dado mucho de que hablar. Esta vez, Android, nos ofrece un nuevo lenguaje visual denominado: “Material Design”, que si bien es muy atractivo, no era compatible con las versiones anteriores del Robot de Google.

Poco a poco se han visto aplicaciones que se adaptan a este nuevo diseño, ignorando la versión con la que corren y esto es gracias a herramientas que aprenderemos con este pequeño proyecto. Trate de simplificarlo en pasos muy puntuales, ademas de dos diseños diferentes (uno en cada branch del repositorio), recuerda que cualquier duda me encuentras en twitter como @thespianartist.







Paso 1: Tener actualizado tu entorno de trabajo:


Vale la pena recordar que Android Studio es el IDE oficial para el desarrollo de aplicaciones móviles para Android (incluyendo Wear, Auto y Glass), por lo que si aun trabajas bajo eclipse (pronto sin soporte), ten prioridad en actualizar pronto a este IDE que, actualmente ya dejó de ser Beta y la experiencia de usuario al estar creando proyectos es única.



Así mismo, antes de iniciar cualquier proyecto, es importante ver el conjunto de librerías y SDKs con los que estaremos trabajando y que de igual manera deben estar actualizados. Recuerda que esto se logra gracias al SDK Manager.



Paso 2: Creando el proyecto y agregando las librerías necesarias:


Vamos a crear un nuevo proyecto, en este caso la versión mínima puede ser a partir de Ice Cream Sandwich 4.0 (API 14). Si te preguntas por Gingerbread, la mayoría del marcado ya omite dicha versión, ya que requiere una reducción importante de features y el beneficio de cubrir las mismas ya no es tanto:



Ademas vamos a usar 4 librerías, 2 del SDK oficial y 2 de terceros:

Código :

    //Librerias standar en el SDK de Android:
    //Necesario para usar Toolbar y configurar el Tema Material en V14+
    compile 'com.android.support:appcompat-v7:21.0.2'

    //Libreria para usar un RecyclerView
    compile 'com.android.support:recyclerview-v7:21.0.0'

    //Librerias de terceros :

    //Libreria para agregar un Floating Action Button
    compile 'com.getbase:floatingactionbutton:1.2.1'

    //Libreria para volver circular una Imagen
    compile 'de.hdodenhof:circleimageview:1.2.1'


Recordar que dichas librerías se agregan en el build.gradle que se encuentra a la altura de la carpeta app, tal como se muestra en la siguiente imagen:



¿Cómo buscar una librería?

Un sitio muy recomendable para consultar las librerías compatibles con Android Studio (y contenidas en el repositorio Maven), es Gradle Please. Cuenta con un buscador excelente, que puede ir desde búsquedas muy especificas como el SDK de facebook, hasta mostrarnos las versiones que tienen actualmente las librerías nativas del SDK, como por ejemplo RecyclerView.



Paso 3: AppCompat, crea un tema compatible con todas las versiones


Recordemos un poco como funciona un tema Material Design, la sugerencia siempre son 3 colores: Primary, Primary Dark and Accent.



Esos 3 colores se pueden elegir de acuerdo a las guías de diseño
de material design. Una vez seleccionados, debemos agregarlos en un archivo colors.xml en la carpeta values, tal como se muestra en la siguiente imagen:

Código :

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="primary_color">#E91E63</color>
    <color name="primary_dark_color">#AD1457</color>
    <color name="accent_color">#69F0AE</color>
</resources>




Ahora modifiquemos styles.xml de la carpeta values, el cual tendrá como tema base AppCompat. AppCompat nos permite dentro de sus muchas propiedades:

1.-Esconder el ActionBar, ya que este será sustituido por un nuevo Widget llamado Toolbar, que es el encargado de dar ese aspecto Material.

2.-Agregar los colores previamente elegidos en colors.xml a toda la aplicación.

Código :

<resources>

    //Darle el aspecto material, necesitamos configirar
    <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">

        <item name="colorPrimary">@color/primary_color</item>
        <item name="colorPrimaryDark">@color/primary_dark_color</item>
        <item name="colorAccent">@color/accent_color</item>

    </style>

</resources>




La ultima configuración que necesita AppCompat para funcionar es nuestra Actividad extienda de ActionBarActivity, no te preocupes, tiene todos los base que tendría un Activity normal :

Código :

public class MainActivity extends ActionBarActivity {

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

    }




Paso 4: Toolbar, un ActionBar Personalizado


Así como AppCompat nos permite personalizar un tema, toolbar nos permite crear nuestro propio ActionBar, inclusive, al punto de llevarlo a necesidades muy puntuales de personalización. Toolbar se maneja como un archivo toolbar.xml dentro de nuestra carpeta de layout.

Para que quede un poco mas claro las posibilidades del widget, el proyecto se basa en dos configuraciones diferentes:

El primero no es nada ajeno a lo que haz visto antes, se trata de un ActionBar de un tamaño estándar y que hereda el color primario que configuramos:

Código :


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



De lo cual, es importante repasar lo siguiente:

android:id="@+id/activity_my_toolbar
Es importante asignarle un ID a nuestro widget,ya que va ser usado por nuestro Activity principal.

android:minHeight="?attr/actionBarSize"
Esto indica el tamaño del widget y si lo quieres ver así, de nuestro ActionBar. Para este ejemplo "heredamos" un párametro llamado actionBarSize que para fines prácticos, es una constante que nos entrega el tamaño por defecto de un ActionBar, ni mas, ni menos.

android:background="@color/primary_color"
Esto indica el color de fondo del ActionBar, para hacer referencia al declarado en colors.xml, lo hacemos mediante @color/primary_color.

app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
Esto es importante, vamos a sobreescribir el ActionBar partiendo de un tema base, en este caso se trata de AppCompat.Dark.ActionBar. Esto hace que el fondo por defecto sea negro (Pero en este caso lo cambiamos a primary_color) y la letra de titulo sea color blanca. Si quisiéramos que el color de texto fuera negro, basta extender de AppCompat.Light o de cualquiera de los temas disponibles:



app:popupTheme="@style/ThemeOverlay.AppCompat.Dark.ActionBar
Esto es lo mismo para lo anterior solo que aplicable al contexto de los menús, podemos decidir si un menú se presenta del mismo tema o diferente al del ActionBar. Esto quiere decir que podemos tener un tema exclusivo para la aplicación y otro propio para el menú. En este caso lo deje igual, pero es elección tuya iterar sobre todas las posibilidades.

Una vez elegidos configurado el Toolbar procedemos a setearlo en nuestra Actividad, es muy sencillo, lo que hacemos primero es el llamado como objeto del Widget:

Código :

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

Y de inmediato setearlo:

Código :

setSupportActionBar(toolbar);


En nuestra actividad principal, en nuestra vista activity_main.xml, heredamos el Toolbar que creamos como toolbar.xml (Debe ser siempre el primer Widget), tal como se muestra en la siguiente imagen:



Código :

   <include
        layout="@layout/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />


Como un paso opcional podemos cambiar el nombre del ActionBar, la siguiente imagen muestra el código implementado:



Y listo, ya tenemos el UI de la aplicación totalmente configurada, que queda de la siguiente manera:



Si notaste, en versiones anteriores a Lollipop, el StatusBar no cambia de color, pero en Android 5.0 si lo hace, pero a pesar de eso, conservan ese mismo look Material Design, y totalmente compatible para todos. Ahora veamos su segunda variante:




Lo único que cambia es el tamaño del ActionBar, que pasa de ser estándar a ser un poco grande (100dp), cosa que antes era imposible sin Toolbar, después puedes usar tu imaginación, podrías agregar widgets del tipo Button, ImageView o hasta Fragment.

Código :

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_my_toolbar"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minHeight="100dp"
    android:background="@color/primary_color"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>


Paso 5: Agregando un Floating Action Button



No hay duda que Floating Action Button es un elemento que de inmediato lo relacionamos con Material Design, existen muchas formas de agregarlo, pero esta vez, optare por una librería hecha especialmente para ello (recordar que ese librería la agregamos en el paso 2):



Lo único que tenemos que hacer es agregar el widget en la vista que queremos, la configuración básica de la librería es:

Código :

        <com.getbase.floatingactionbutton.FloatingActionButton
            android:id="@+id/pink_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            fab:fab_icon="@drawable/ic_add"
            fab:fab_colorNormal="@color/accent_color"
            fab:fab_colorPressed="@color/accent_color" />


Donde:

android:id="@+id/pink_icon"
Es el id que le asignamos al botón, con ello, podemos manipularlo fuera de nuestra vista, como por ejemplo, escuchar eventos "onClick"

android:layout_width="wrap_content"
Siempre se debe configurar el ancho con el contenido que necesite, nunca con todo el disponible.

android:layout_height="wrap_content"
Siempre se debe configurar el alto con el contenido que necesite, nunca con todo el disponible.

fab:fab_icon="@drawable/ic_add"
Es el icono dentro del botón, y dicho icono es una imagen contenida dentro de nuestras carpetas drawable, como tip Google tiene como descarga todos los iconos basados en Material Design.

fab:fab_colorNormal="@color/accent_color"
fab:fab_colorPressed="@color/accent_color"
Y estos últimos son los colores que tendrá el botón, precisamente como recomendación es el color Accent, configurado previamente en colors.xml.

Lo se, nuestro diseño muestra dos variaciones y parecieran muy diferentes entre ellas, pero lo único que cambia de nuestro botón es la posición, nada mas. La siguiente imagen muestra los cambios entre ellos (recuerda que todo el código se menciona en el paso 1):




Realmente ya configuramos lo importante del UI, esto es la base de una aplicación Material Design, todo lo demás depende mucho de lo que quieras hacer: Tabs, Navigation Drawer, Listas, etc. Solo como ejemplo, en este casó, use un RecyclerView para desplegar una lista de elementos, no seré muy especifico ya que fue algo que nos enfocamos mucho en otro tutorial.

Paso 6: Nuestro viejo amigo RecyclerView



Ya como punto final de este pequeño proyecto, tenemos a un viejo conocido, un RecyclerView. Recordar que en un RecyclerView se crea:

Un modelo (En este caso se llama Pusheen.java):

Código :

public class Pusheen {
    private Integer id;
    private String name;
    private String pasTime;

    public String getPasTime() {
        return pasTime;
    }

    public void setPasTime(String passTime) {
        this.pasTime = passTime;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}



Una Vista (row.xml dentro de layout y es donde ademas usamos la librería para imágenes circulares):

Código :


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:layout_marginLeft="16dp"
    android:layout_marginTop="10dp"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/image"
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:src="@drawable/pusheen"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Pusheen"
        android:id="@+id/name"
        android:textStyle="bold"
        android:textColor="#424242"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/image"
        android:layout_toEndOf="@+id/image"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="10dp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="pastime"
        android:textColor="#424242"
        android:id="@+id/passtime"
        android:layout_below="@+id/name"
        android:layout_alignLeft="@+id/name"
        android:layout_alignStart="@+id/name" />
</RelativeLayout>


Un Adapter (PusheenAdapter.java):

Código :

package la.mejorando.prelollipopmaterialdesign.adapters;

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 java.util.ArrayList;

import la.mejorando.prelollipopmaterialdesign.R;
import la.mejorando.prelollipopmaterialdesign.models.Pusheen;

/**
 * Created by thespianartist on 07/12/14.
 */
public class PusheenAdapter extends RecyclerView.Adapter<PusheenAdapter.ViewHolder> {

    private ArrayList<Pusheen> pusheenArrayList;
    private int itemLayout;


    public PusheenAdapter(ArrayList<Pusheen> data,  int itemLayout){

        this.pusheenArrayList = data;
        this.itemLayout = itemLayout;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public ImageView image;
        public TextView name;
        private TextView pasTime;

        public ViewHolder(View itemView) {

            super(itemView);
            image = (ImageView) itemView.findViewById(R.id.image);
            name = (TextView) itemView.findViewById(R.id.name);
            pasTime = (TextView) itemView.findViewById(R.id.passtime);

        }
    }

    @Override
    public PusheenAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int i) {
        View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false);
        ViewHolder viewHolder = new ViewHolder(itemLayoutView);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(PusheenAdapter.ViewHolder viewHolder, int position) {

        Pusheen pusheen = pusheenArrayList.get(position);

        viewHolder.name.setText(pusheen.getName());
        viewHolder.pasTime.setText(pusheen.getPasTime());

        if (pusheen.getId()!=null) {
            switch (pusheen.getId()) {
                case 1:
                    viewHolder.image.setImageResource(R.drawable.pusheen);
                    break;

                case 2:
                    viewHolder.image.setImageResource(R.drawable.pusheen2);
                    break;

                case 3:
                    viewHolder.image.setImageResource(R.drawable.pusheen3);
                    break;

                case 4:
                    viewHolder.image.setImageResource(R.drawable.pusheen4);
                    break;

                case 5:
                    viewHolder.image.setImageResource(R.drawable.pusheen5);
                    break;
            }

        }else{
            viewHolder.image.setImageResource(R.drawable.pusheen);
        }
        viewHolder.itemView.setTag(pusheen);
    }

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



y propiamente el Widget dentro de la vista

Código :

 <android.support.v7.widget.RecyclerView
        android:layout_marginTop="?attr/actionBarSize"
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />




Y eso es todo, tenemos un lindo proyecto Material Design para versiones anteriores a Lollipop, les dejo una ultima imagen de la aplicación vista en horizontal:





Recuerden que si tienen alguna pregunta no olviden consultarme en twitter @thespianartist, les dejo de nuevo el repositorio del ejemplo (Recuerden que tiene dos branches). Ademas, me gustaría saber si esto aporto en sus proyectos actuales (:

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate