Controles: Tutorial De Botones En Android

En este tutorial veremos cómo usar botones en Android con el fin de que los usuarios de tu app puedan interactuar con el contenido.

Primero estudiarás la clase Button que es la encargada de representar botones en la UI. Luego verás cómo añadir eventos de click. También cómo se clasifican según el Material Design, cómo crearlos en Android Studio y por último a personalizar su estilo.

1. Implementar Un Botón En Android

Crear Proyecto en Android Studio

Antes que nada abre Android Studio, ve al menú de herramientas y selecciona File > New > New Project… para crear un nuevo proyecto.

Crear nuevo proyecto en Android Studio

En la configuración del proyecto ten en cuenta los siguientes parámetros:

  • Application Name: usa el nombre “Botones”.
  • Company Domain Name: Para el dominio elige la entidad que represente tu creación, puede ser tu_nombre.com, el nombre_de_tu_empresa.com o simplemente test.com.
  • Projection Location: En la ubicación selecciona la carpeta que tengas destinada para guardar tus proyectos. Recuerda no usar espacios en ni caracteres especiales con acentos.

Ahora en los factores de forma deja por defecto el SDK mínimo de ejecución en la versión 11 de Android.

Seleccionar factor de forma mínimo para ejecución de app Android

En la siguiente venta elige una actividad vacía (Empty Activity) cómo contenedor principal para los ejemplos que veremos:

Añadir actividad vacía en Android Studio

Finalmente cambia el título del archivo java para la actividad por ActividadBotones.java al igual que su layout (actividad_botones.xml). Al presionar Finish tendrás un proyecto de prueba el cual te servirá para seguir todo el tutorial.

Personalizar actividad vacía en Android Studio

La Clase Button

Un botón es un control con texto o imagen que realiza una acción cuando el usuario lo presiona. La clase Java que lo represente es Button y puedes referirte a él dentro de un layout con la etiqueta <Button> respectivamente.

Ejemplo de button en Android

Para agregar un botón a la actividad principal de tu app dirígete a actividad_botones.xml y agrega la siguiente definición.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.herprogramacion.botones.ActividadBotones">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="AGREGAR" />
</RelativeLayout>

Con ello centramos el botón en el relative layout.

El texto que especifica su acción especifícalo en el atributo android:text. En el ejemplo anterior se usó la palabra "AGREGAR".

Este código debería mostrar en la ventana Preview la siguiente imagen:

Ventana Preview en Android Studio

Atributos de un Botón

Si quieres cambiar las propiedades de un botón recurre a los atributos que la documentación presenta en formato Java o XML.

Debido a que Button extiende de TextView, puedes usar todos los atributos de esta clase.

Algunos de los más utilizados son:

Atributo Descripción
android:text Permite cambiar el texto de un botón
android:background Se usa para cambiar el fondo del botón. Puedes usar un recurso del archivo colors.xml o un drawable.
android:enabled Determinar si el botón está habilitado ante los eventos del usuario. Usa true (valor por defecto) para habilitarlo y false en caso contrario.
android:gravity Asigna una posición al texto con respecto a los ejes x o y dependiendo de la orientación deseada.

Por ejemplo: Si usas top, el texto se alineará hacia el borde superior.

android:id Representa al identificador del botón para diferenciar su existencia de otros views.
android:onClick Almacena la referencia de un método que se ejecutará al momento de presionar el botón.
android:textColor Determina el color del texto en el botón
android:drawable* Determina un drawable que será dibujado en la orientación establecida.

Por ejemplo: Si usas el atributo android:drawableBottom, el drawable será dibujado debajo del texto.

Teniendo en cuenta la anterior tabla te invito a ver los resultados que producen usar algunos de esos atributos.

Cambiar texto de un botón

Asigna una cadena directamente al atributo android:text para indicar la acción del botón.

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:text="Agregar" />

Por defecto el texto del botón estará en mayúsculas, pero si quieres deshabilitar esta característica usa el valor false en el atributo android:textAllCaps.

<Button
    ...
    android:textAllCaps="false"/>

Ahora, si deseas cambiar el texto programáticamente usa el método setText().

Para ello abre ActividadBotones.java. Obtén la instancia del botón con findViewById() y luego invoca setText() con una secuencia de caracteres como parámetro.

public class ActividadBotones extends AppCompatActivity {

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

        Button boton = (Button) findViewById(R.id.button);
        boton.setText("Ordenar");
    }
}

Esto produce el siguiente resultado:

Cambiar texto de botón en Android programáticamente

Ahora también es posible asignar un recurso string al texto del botón desde XML y Java.

En caso de XML usa la notación de recurso @string o @android:string (strings del sistema) de la siguiente forma:

<Button
    ...
    android:text="@string/texto_agregar"/>

En Java solo usa el operador punto para llegar al identificador perteneciente a la clase R:

Button boton = (Button) findViewById(R.id.button);
boton.setText(R.string.texto_agregar);

Cambiar Color de Fondo

Modificar el fondo de un botón implica el cambio del atributo android:background por un recurso de color o drawable.

Ejemplo:

Usar el color primario del proyecto como color de background de un botón

Solución:

Invoca la referencia @color/colorPrimary de tu archivo values/colors.xml:

<Button
    ...
    android:background="@color/colorPrimary"/>

El resultado es:

Cambiar background de botón en Android

Sin embargo, hacer esto hace perder la reacción de superficie que se tenía antes por el Material Design.

La forma redondeada tampoco se hace presente.

Solo queda la elevación al momento de tocar el botón.

Para conservar el efecto y cambiar el color del botón usa el atributo app:backgrountTint de la siguiente forma:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.herprogramacion.botones.ActividadBotones">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        app:backgroundTint="@color/colorPrimary"
        android:text="@string/texto_agregar" />
</RelativeLayout>

Así tendrías:

Usar atributo app:backgroundTint en botón Android

Botón con Texto e Imagen

En la sección de atributos viste que existen atributos con la forma android:drawable* para alinear una imagen al texto de un botón.

Para demostrar su uso veamos el siguiente ejemplo sencillo.

Alinear a la izquierda del botón ordenar un icono asociado a pizzas.

Solución

Abre el layout actividad_botones.xml y agrega un botón centrado en el padre. Cambia el color de texto a blanco (@android:color/white), usa un tinte de color rojo (#ef9a9a) y alinea a la izquierda el siguiente drawable de pizza:

Icono de pizza en Android

Tu código debería quedar de la siguiente forma:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.herprogramacion.botones.ActividadBotones">


    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:drawableLeft="@drawable/ic_pizza"
        android:drawablePadding="8dp"
        android:id="@+id/boton"
        android:textColor="@android:color/white"
        app:backgroundTint="#ef9a9a"
        android:text="Ordenar"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

Y el resultado sería:

Botón para ordenar pizza en app Android

Como ves, usé android:drawableLeft para ubicar la imagen en la izquierda. Si compruebas con las sugerencias de Android tendrás varias posiciones: derecha, abajo y arriba.

Android Studio: Sugerencias atributo android:drawable* en Button

La Clase ImageButton

ImageButton funciona exactamente cómo Button, solo que en lugar de traer un texto en su background, viene una imagen para especificar la acción.

Para cambiar la imagen de un image button usa el atributo android:src. Obviamente su valor es un drawable.

El contorno del background se conserva como lo hemos visto hasta ahora, la diferencia está que en el centro se
ubicará la imagen elegida en src.

Si quieres que el background por defecto desaparezca, asigna un color transparente o cambia el contenido con un list drawable (esto lo verás más adelante).

Ejemplo:

Cambiar la imagen de un image button con el icono de la app.

Solución

Lo primero es abrir el layout de la actividad y añadir un elemento <ImageButton> centrado en el relative layout.

El icono de la aplicación actual se encuentra en la referencia @mipmap/ic_launcher. Así que asigna este valor al atributo andriod:src.

Adicionalmente puedes el color del sistema @android:color/transparent sobre android:background para eliminar el contorno. Pero recuerda que esto elimina los efectos del Material Design.

<ImageButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/boton"
    android:src="@mipmap/ic_launcher"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true" />

Ejecuta la app y verás la apariencia del botón final:

Ejemplo de ImageButton en Android

Crear Botón Desde Android Studio

Usa la pestaña Design que se ve en la vista de un layout para arrastrar y soltar un botón desde la paleta o cambiar sus atributos.

Pestaña Design en Android Studio

1. Sitúate en la ventana Palette. Luego busca el elemento Button de la sección Widgets

Android Studio: Button en la sección Widgets de la Paleta

2. Lleva el puntero del mouse hacia el layout y ubícalo según tu objetivo. En mi caso tengo un RelativeLayout, el cual permite orientar mi botón en lugares asociados al contenido del padre y al de otros views.

Por el momento lo ubicaré en el centro absoluto del layout, donde el editor mostrará líneas de guía para saber que valores estoy otorgando:

Ubicación de botón en el centro de un RelativeLayout

3. Una vez elegido el lugar donde se ubicará el botón, confirma con un click su inserción. Esto mostrará en la ventana Properties todos los atributos del botón que puedes editar.

Ubicación de botón en layout

4. Si deseas, da doble click sobre el botón en el layout para desplegar una caja de edición rápida para el id y el texto.

Edición rápida en pestaña Design de un botón

Tipos De Botones En Material Design

La documentación sobre botones en el Material Design nos habla de tres tipos:

  • Raised Buttons
  • Flat Buttons
  • Floating Action Buttons (FAB)

Los raised buttons son los que hemos visto hasta ahora. Tienen backgrounds rectangulares, se elevan ante el click del usuario y su superficie reacciona con un efecto ripple.

Se usan sobre layouts que tienen gran variedad de contenido para delimitar las secciones o elementos. Además realzan la importancia de realizar una acción relacionada.

Raised Butto en Android

Por el contrario, un flat button o botón sin bordes tiene reacción de superficie pero no se eleva al ser presionado. Se usan para acciones en diálogos, toolbars y de forma persistente en steppers.

Flat Button en Android

El Floating action button tiene las mismas interacciones de elevación y ripple que el raised button, solo que este tiene forma circular. Su objetivo es promover una acción principal relacionada a una pieza de material.

Floating Action Button en Android

Manejar Los Eventos De Un Botón

Es de esperar que un botón dispara un evento al ser clickeado por un usuario, lo que permitirá ejecutar la acción a la que hace referencia dicho view.

Para procesar el evento existen varias formas de proceder.

Usar el Atributo android:onClick

Anteriormente cuando viste la clase Button se mencionó la existencia de android:onClick() para asignar un método que se ejecute cuando el usuario presione el botón.

Para ello se requiere que el método cumpla con las siguientes condiciones:

  1. Que sea público
  2. Que sea tipo void
  3. Que reciba un parámetro del tipo View
  4. Debe declararse en la actividad que usa el mismo layout

Ejemplo:

Cambiar el texto de un Text View por el mensaje “Botón presionado: [hora_actual]” al presionar un Button.

Solución:

Comienza por añadir un text view al layout. En mi caso lo ubicaré en el centro del relative layout y por debajo pondré el botón:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.herprogramacion.botones.ActividadBotones">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/texto_agregar"
        android:layout_below="@+id/textView"
        android:layout_centerHorizontal="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="A la espera..."
        android:id="@+id/textView"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

Ahora en la actividad ActividadBotones crearé un método para los clicks llamado cambiarMensaje().

La idea es obtener el text view como campo para poder cambiar su texto con setText() desde el método.

Para obtener la hora usa la clase Calendar y para formatear su estructura usa SimpleDateFormat.

ActividadBotones.java

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class ActividadBotones extends AppCompatActivity {

    private TextView texto;

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

        texto = (TextView) findViewById(R.id.textView);
    }

    public void cambiarMensaje(View v){
        SimpleDateFormat formato = new SimpleDateFormat("HH:mm:ss");
        Date fechaActual = Calendar.getInstance().getTime();
        
        String s = formato.format(fechaActual);
        texto.setText(String.format("Botón presionado: %s", s));
    }
}

Lo siguiente es dirigirse al layout y asignar el método en el botón con android:onClick. Al momento de hacerlo, el motor de Android Studio debe sugerirte que cambiarMensaje() está disponible.

Atributo android:onClick en Button

El atributo quedaría de la siguiente forma:

<Button
    ...
    android:onClick="cambiarMensaje"/>

Al ejecutar la app y clickear el botón tendrás el cambio de texto por la hora actual.

Ejemplo app Android con android:onClick button

Usar Escucha Anónima OnClickListener

Otra forma es crear una instancia anónima de la interfaz View.OnClickListener para manejar los eventos del botón.

Esto requiere usar el método setOnClickListener() para asignar el listener al botón y luego sobrescribir el controlador onClick() con las acciones a ejecutar.

Ejemplo:

Iniciar otra actividad al presionar un botón

Solución

Lo primero es añadir otra actividad al proyecto actual que tienes abierto (recuerda quitar el text view que se tenía antes y la referencia de android:onClick()).

Ve al menú de herramientas y presiona File > New > Activity > Empty Activity

Android Studio: Crear nueva actividad

Nombra a la nueva actividad como “ActividadNueva” y confirma.

Nueva Empty Activity en Android Studio

Lo siguiente es ir ActividadBotones y obtener la instancia del botón que tenemos en onCreate().

Luego invoca el método setOnClickListener() desde la instancia y como parámetro digita solamente "new O". Esto es suficiente para que Android Studio te recomiende la creación de un nuevo OnClickListener.

Android Studio: Sugerencia de new OnClickListener

Al presionar ENTER o clickear la sugerencia, Android Studio creará la escucha anónima junto a la implementación del controlador onClick():

Button boton = (Button) findViewById(R.id.button);
boton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        
    }
});

Ahora dentro del controlador crea un nuevo Intent para iniciar la actividad ActividaNueva. Seguido invoca startActivity() para hacer efectivo el inicio.

Button boton = (Button) findViewById(R.id.button);
boton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent i = new Intent(ActividadBotones.this, ActividadNueva.class);
        startActivity(i);
    }
});

Usar OnClickListener Sobre el Contenedor

OnClickListener también puede ser implementada sobre el contenedor del botón como lo es una actividad o un fragmento.

Así podrás sobrescribir el controlador onClick() para que tenga un alcance global para todos los views que pertenezcan al contenedor. Lo que es de utilidad si se deseas leer clicks sobre varios elementos al tiempo.

Ejemplo:

Cambiar el color del background de una actividad dependiendo de qué botón de 4 disponibles se presione.

Solución:

Pon 4 botones centrados horizontalmente y uno debajo de otro dentro del relative layout. Usa los siguientes colores en sus textos: Verde azulado, Verde, Verde claro y Lima.

actividad_botones.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.herprogramacion.botones.ActividadBotones">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Verde azulado"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Verde"
        android:id="@+id/button2"
        android:layout_below="@+id/button"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Verde claro"
        android:id="@+id/button3"
        android:layout_below="@+id/button2"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Lima"
        android:id="@+id/button4"
        android:layout_below="@+id/button3"
        android:layout_centerHorizontal="true" />


</RelativeLayout>

Implementa la escucha OnClickListener sobre la ActividadBotones:

public class ActividadBotones extends AppCompatActivity implements View.OnClickListener {

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

Si dejas el código como está, Android Studio te informará que hay un error porque no has sobreescrito el controlador.

Android Studio: Error "Implement abstract method onClick()"

La solución manual sería escribir la firma y cuerpo del método como es requerido. Sin embargo puedes usar la generación de código automático de Android Studio.

Presiona ALT + insert dentro del cuerpo de la clase y selecciona Implement Methods…

Android Studio: Generador de implement methods

Luego selecciona onClick() del menú y confirma.

Android Studio: Seleccionar métodos a implementar

Con ello construirás el cuerpo de forma automática:

@Override
public void onClick(View v) {
    
}

Lo que sigue es detectar los eventos de click con múltiples botones.

Una de las formas más sencilla es usar una sentencia switch, donde su expresión de validez sea el identificador del view que viene como parámetro de onClick().

El algoritmo sería el siguiente:

  • Asignar la escucha a todos los botones con el operador this.
  • Obtener el view raíz de la jerarquía con getRootView().
  • Abrir un switch con el id del view clickeado. El id se obtiene con el método getId().
  • Elegir el color dependiendo del caso. Convierte una definición hexadecimal en entero con Color.parseColor().
  • Cambiar el background del contenedor con el método setBackgroundColor()

Veamos:

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

public class ActividadBotones extends AppCompatActivity implements View.OnClickListener {

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

        findViewById(R.id.button).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
        findViewById(R.id.button3).setOnClickListener(this);
        findViewById(R.id.button4).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {

        int color;

        View contenedor = v.getRootView();

        switch (v.getId()) {
            case R.id.button:
                color = Color.parseColor("#80CBC4"); // Verde azulado
                break;
            case R.id.button2:
                color = Color.parseColor("#A5D6A7"); // Verde
                break;
            case R.id.button3:
                color = Color.parseColor("#C5E1A5"); // Verde claro
                break;
            case R.id.button4:
                color = Color.parseColor("#E6EE9C"); // Lima
                break;
            default:
                color = Color.WHITE; // Blano
        }

        contenedor.setBackgroundColor(color);
    }
}

Ejecuta la app y prueba clickear los 4 botones para cambiar el background de la actividad.

Eventos de click con múltiples botones en Android

Personalizar El Estilo De Un Botón

Ya viste algunos atributos que puedes cambiar en los botones para transformar su apariencia. Con eso puedes ir a tu archivo styles.xml y crear estilos para estos views.

A continuación te mostraré algunos casos que pueden presentarse a la hora de querer personalizar un botón.

Cambiar Background

Si quieres omitir la forma por defecto del botón y los efectos de reacción, puedes probar usando un recurso drawable del tipo State List.

Este elemento representa múltiples drawables que serán usados en un mismo view simulando cambio de estados.

Esto se ajusta perfectamente a los botones ya que su apariencia varía según la interacción.

Ejemplo:

Crear background de un botón con diseño plano (Flat Design) 

Solución:

Lo primero que harás es crear un nuevo drawable llamado bk_boton_plano.xml.

Para ello ve a la carpeta drawable, presiona click derecho y selecciona Drawable resource file.

Android Studio: Crear nuevo drawable resource file

Confirma el nombre con OK:

New resource file en Android Studio

La definición XML requiere que el nodo principal sea del tipo <selector>.

Dentro de este deben existir elementos <item> que definan el drawable que asignará a cada estado del botón.

Existen cuatro estados primordiales:

  • normal
  • enfocado (state_focused)
  • presionado (state_pressed)
  • deshabilitado (state_enabled > false).

Con lo anterior el código quedaría así:

bk_boton_plano.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/boton_presionado"
        android:state_pressed="true" />
    <item android:drawable="@drawable/boton_enfocado"
        android:state_focused="true" />
    <item android:drawable="@drawable/boton_deshabilitado"
        android:state_enabled="false" />
    <item android:drawable="@drawable/boton_normal" />
</selector>

Cada drawable de estado se compone de una lista de capas de drawables para simular un borde sombreado inferior.

El estado normal tiene asignado el drawable boton_normal.xml el cual tiene dos en tono naranja profundo.

boton_normal.xml

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

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Sombra -->
    <item android:top="4dp">
        <shape>
            <solid android:color="#FF7043" />
            <corners android:radius="4dip" />
        </shape>
    </item>
    <!-- Contenido -->
    <item android:bottom="4dp">
        <shape>
            <solid android:color="#FF8A65" />
            <corners android:radius="4dip" />
        </shape>
    </item>
</layer-list>

El estado de foco simplemente cambia los colores de ambas capas para visualizar un cambio minimo de contraste.

boton_enfocado.xml

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

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Sombra -->
    <item android:top="4dp">
        <shape>
            <solid android:color="#FFCA28" />
            <corners android:radius="4dip" />
        </shape>
    </item>
    <!-- Contenido -->
    <item android:bottom="4dp">
        <shape>
            <solid android:color="#FFD54F" />
            <corners android:radius="4dip" />
        </shape>
    </item>
</layer-list>

Y el botón presionado es exactamente lo mismo. Un aumento de opacidad en el tono.

boton_presionado.xml

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

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Sombra -->
    <item android:top="4dp">
        <shape>
            <solid android:color="#FFA726" />
            <corners android:radius="4dip" />
        </shape>
    </item>
    <!-- Contenido -->
    <item android:bottom="4dp">
        <shape>
            <solid android:color="#FFB74D" />
            <corners android:radius="4dip" />
        </shape>
    </item>
</layer-list>

Con esos drawables listos, ahora puedes ir al layout de la actividad y modificar el atributo android:background para asignar la lista. Cambia el color de texto con android:textColor a blanco para mejorar el contraste y si deseas desaparecer la animación de elevación, usa android:stateListAnimator con el valor de @null.

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:textColor="@android:color/white"
    android:background="@drawable/bk_boton_plano"
    android:stateListAnimator="@null"
    android:text="@string/texto_agregar" />

Este serían los estados logrados:

Flat button en Android con state list drawables

Estilo BorderLess o Botón sin Bordes

Ya habías visto que el botón sin bordes se le denomina Flat button en el Material Design.

Para crear dicho acabado puedes aplicar el estilo Widget.AppCompat.Button.Borderless.

Por ejemplo…

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Llamar"
    style="@style/Widget.AppCompat.Button.Borderless"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true" />

Produciría el siguiente resultado:

Botón con estilo BorderLess en Android

Si deseas que el color del texto sea el mismo del acento, entonces usa Widget.AppCompat.Button.Borderless.Colored.

Botón con estilo BorderLess.Colored en Android

Conclusión

Los botones son unos de los widgets más básicos en Android.

Tienen la función de ayudar al usuario a decidir por sus acciones sobre el contenido y datos de la app.

Saber describir su comportamiento con OnClickListener es vital para las interacciones. Recuerda que las acciones se ubican en el controlador onClick().

O puedes usar el editor de diseño en Android Studio para asignar el método en el atributo android:onClick.

Usa el estilo correcto según lo hablado en la sección de Material Design. Es decir: Raised buttons para acciones estables, Flat buttons para confirmaciones o acciones repetitivas y el Floating action button para promover acciones principales sobre datos.

  • José

    Excelente tutorial. Nada más quería consultarte que diferencia hay entre los atributos que comienzan con “android:”, “app:” y “tool:”, muchas gracias.

    • Gracias José.

      El namespace “android” es estándar en los componentes android representados en XML.

      “app” hace referencia a un atributo que hace parte de una librería de soporte.

      Y “tool” es una namespace especial para la previsualización de características de un layout en la ventana “Preview”, pero que no afectan en la ejecución real.

  • Michael Roa

    Muy bueno tus tutoriales!!

  • Gon Her

    Muy buen tutoria! Te hago una pregunta: Se puede aumentar los corner redondeados? aumentar el redondeado por ejemplo a 5/6 dp?
    Saludos

    • Si claro Gon, si hablas del personalizado solo ve a los drawables y cambia el 4dpi de android:radius por el valor que quieras.

  • Alejandro

    Hola,

    Muy buen tutorial, como todos los demás :) Hace unos días te envié un correo con propuestas para nuevos tutoriales. ¿Te ha llegado? Estaba interesado en un tutorial en el que uses un ViewPager para crear un Slideshow y si puedes, con un indicador para saber en que imagen estás. Algo tipo a la imagen que te pongo aquí abajo, pero en plan guay, con animaciones y esas cosas que tu haces jaja
    Sigue currando así de bien, que da gusto ver como tus tutoriales son de lo mejor que hay en la red.
    Saludos

    http://i.stack.imgur.com/Drb08.png

    • Hola Alejandro.

      Lo siento por no responderte, la verdad es que me llegan demasiados correos con preguntas y me es imposible contestarlos todos. Al igual me pasa con los comentarios que me dejan. Pero eso no significa que los ignore.

      En cuanto al tuto que me dices, ya lo tengo en mi lista de temas. No se para cuando vaya a salir, por lo que no podría prometerte un fecha. Pero tenlo por seguro que lo voy a escribir.

      Saludos y gracias por seguir mi blog compañero!

      • Alejandro

        Lo esperaré con ganas.
        Saludos

  • Lucas Emanuel Ortiz

    Excelente Material! Adhiero a webserveis y sería muy util un tutorial sobre autenticación o implementación de AbstractAccountAuthentication!!

  • Cuando puedas, me gustaría un tutorial sobre el viewSearch, que estoy un poco encallado a la hora de mostrar resultados, algunos hablan tablas virtuales, otros arrays de objetos etc… que si content providers para el quicksearch, ultima entradas, sugerencias etc… Hay muy poco documentación práctica sobre eso.

  • Cuando puedas, me gustaría un tutorial sobre el viewSearch, que estoy un poco encallado a la hora de mostrar resultados, algunos hablan tablas virtuales, otros arrays de objetos etc… que si content providers para el quicksearch, ultima entradas, sugerencias etc… Hay muy poco documentación práctica sobre eso.

  • Felicidad para el tuto muy completo para crear botones raised, flat etc… Pero veo que te has descuidado en como indicar para cambiar el color del ripple.

    id_color

    • Gracias por el aporte compañero. Para los ripple pienso crear un tuto mas adelante.

      Saludos!

    • Gracias por el aporte compañero. Para los ripple pienso crear un tuto mas adelante.

      Saludos!

  • Luis David Guzman

    Siiiii !!!!!! Fantastico excelten tutorial, muy bueno y muy bien explicado xD, Muchas Gracias por tan excelente material !!!

  • Ricky

    Eres el puto amo james….bien explicado,todos los casos posibles, explicado clarito y con gráficos esclarecedores.
    Solo un pequeño “pero” no has planteado hacer videotutoriales se hacen más livianos para nosotros
    Eres el mejor james

    • ajjajaja gracias Ricky. Esa la idea, especificar los casos que más puedan presentarsenos.

      Mmm los videos aún no los tengo previstos, pero es buena idea.

      Saludos!

    • Yo los videotutoriales no me gustan para nada en temas de programación, aportan menos en contenido, cuando conoce un poco sobre la materia te abures, en cambio los tutoriales vas directo al grano, o bien puedes tener una mejor vista general del tutorial, poder situarte en cualquier parte del tutorial para comprender mejor la cosa.
      Los videotutoriales solo sirven para determinadas cuestiones y no por mostrar bloques de código enteros, sino pequeñas funcionalidades (introducción de lenguajes, patrones de diseño, funcionalidades del ide). Los tutoriales de james son muy extensos y muy prácticos, a veces complicados de entender “el sistema,patrón etc..”, si no tienes siempre todo el código a la vista.

    • Yo los videotutoriales no me gustan para nada en temas de programación, aportan menos en contenido, cuando conoce un poco sobre la materia te abures, en cambio los tutoriales vas directo al grano, o bien puedes tener una mejor vista general del tutorial, poder situarte en cualquier parte del tutorial para comprender mejor la cosa.
      Los videotutoriales solo sirven para determinadas cuestiones y no por mostrar bloques de código enteros, sino pequeñas funcionalidades (introducción de lenguajes, patrones de diseño, funcionalidades del ide). Los tutoriales de james son muy extensos y muy prácticos, a veces complicados de entender “el sistema,patrón etc..”, si no tienes siempre todo el código a la vista.

  • sergio morales

    Wooow, esto es justo lo que estaba buscando hace 2 días, como siempre un excelente tutorial, me has resuelto muchas dudas, magnifico trabajo.