Si tuviera que elegir los dos componentes más habituales para hacer una app, yo lo tengo claro, serían los TextView y los Button. En este capítulo empezaremos por los botones, comprendiendo todo el potencial que le podemos sacar para dejar una app lo más profesional posible.
Botones en Kotlin
Necesitamos tener claro el uso principal de un botón, permitir al usuario realizar interacciones con la aplicación. Un botón por código sería esto:
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Text button" />
Este simple código nos permite un botón muy sencillo, pero en este capítulo vamos a indagar más a fondo hasta darle la vuelta a lo que conocemos sobre ellos.
Let’s code
Como ya comenté en el capítulo anterior, seguiremos usando el mismo proyecto para el cual solo teníamos una pantalla con un diseño distinto al que viene por defecto. Pues lo primero que haremos será crear una nueva activity donde trabajaremos con los botones. Como ya sabéis botón derecho sobre el directorio principal New>Activity>Empty Activity.

Creando ButtonActivity
Yo la llamaré ButtonActivity, y un vez creada vamos a su layout.
A partir de ahora debemos olvidar usar la etiqueta <Button> para crear botones, pues esos eran los botones genéricos. Recordad que hemos añadido la librería de Material Design, por lo que vamos a empezar a usar sus botones.
<com.google.android.material.button.MaterialButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Text button" />
Este será el nuevo botón, tiene un nombre más largo pero Android Studio autocompleta, basta con poner MaterialButton y nos saldrá.
Según las guías de diseño de material, deberemos usar los botones con cierto control y algunas normas que veremos a continuación, lo primero será especificar los cuatro tipos de botones que nos podemos encontrar.
Contained Button
El primer tipo de botón y el más común. Básicamente será igual que los antiguos botones, este al ser el botón por defecto no necesitará ningún estilo en su declaración. Su uso es para acciones primarias, es decir, la acción más acertada para el usuario.

Botón tipo Contained
Para capturar la respuesta del botón, bastaría con hacer un simple listener con la id del botón. Recordemos que un lístener es simplemente una función que está «escuchando» hasta que salta la acción qué espera, en este caso, que se presione el botón.
<com.google.android.material.button.MaterialButton android:id="@+id/containedButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="30dp" android:text="Contained Button" />
Y en nuestra clase ButtonActivity el listener quedaría así.
containedButton.setOnClickListener{ //La acción que quisiéramos hacer }
Añadiendo iconos
Los botones pueden llevar un icono, para dar más importancia al botón, para ello necesitaremos añadir dos atributos a nuestro botón.
style="@style/Widget.MaterialComponents.Button.Icon" app:icon="@android:drawable/ic_input_add"
Lo primero ha sido añadir un estilo para que asimile que va a llevar un icono, luego con el atributo app:icon le hemos dicho que coja del propio Android Studio el icono ic_input_add.

Botón Contained con icono
Así es como quedaría nuestro icono. Ahora imaginemos que preferimos que el icono esté al final, para ello usaremos el atributo app:iconGravity=end.
Tenemos una gran serie de atributos que podemos aplicar al botón.
Atributos para el texto
Tenemos un gran listado de atributos para nuestos contained buttons, yo he añadido los más habituales o los que creo que serán más útiles.
- android:text Añade un texto al botón
- app:icon Añade un icono al botón
- android:strokeColor Añadir una linea que bordea el botón
- app:iconTint Cambia el color del icono
- android:backgroundTint Color del fondo del botón
- app:gravity Con start o end añades el icono antes o después del texto
- android:textColor Define un color para el texto del botón
- app:iconPadding Distancia entre el icono y el texto
- android:elevation Elevación del botón, para crear sombra
- app:iconSize Modifica el tamaño del icono
- android:strokeWidth Selecciona el grosor de la línea (en dp)
Outlined Button
Este botón sería el segundo con más valor y se utiliza para acciones importantes pero no tan importante como la opción anterior. Por ejemplo, un diálogo, que nos avisa de que si aceptamos cerraremos sesión. La acción importante que querría hacer el usuario es cerrar sesión (usaríamos un botón contained) pero para cancelar la acción usaríamos un outlined.

Botón Outlined
Si observamos la imagen anterior veremos que sería como el anterior botón a la inversa, es decir, el fondo transparente, el color del texto opuesto y un stroke (línea que bordea el botón) para definir el ancho y largo del botón.
Antes de continuar, como queremos hacer un catálogo de botones en nuestro layout activity_button, vamos a modificar el layout del fichero para que se vayan centrando y colocando todos en orden.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:gravity="center" android:orientation="vertical" tools:context=".ButtonActivity"> //Todos nuestros botones aquí </LinearLayout>
Hemos hecho un LinearLayout y le hemos dicho que queremos una orientación vertical y un gravity=»center» que con esto conseguiremos que se vayan apilando los botones en el centro de la pantalla verticalmente.
Volviendo al tema anterior, para definir este botón es muy sencillo, simplemente debemos cambiarle el estilo a @style/Widget.MaterialComponents.Button.OutlinedButton.
<com.google.android.material.button.MaterialButton android:id="@+id/outlinedButton" style="@style/Widget.MaterialComponents.Button.OutlinedButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Outlined button" />
Para usar su listener lo haríamos del mismo modo que en el apartado anterior.
outlinedButton.setOnClickListener{ //La acción que quisiéramos hacer }
También podemos añadir un icono del mismo modo que el contained button, pero cambiando el style de este.
<com.google.android.material.button.MaterialButton android:id="@+id/outlinedButtonWithIcon" style="@style/Widget.MaterialComponents.Button.OutlinedButton.Icon" android:layout_width="wrap_content" android:layout_height="wrap_content" app:icon="@android:drawable/ic_input_add" app:iconGravity="start" android:text="Outlined button" />

Botón Outlined con icono
Los atributos son los mismos que el anterior.
Text button
Los botones de texto se usar para acciones menos importantes, estos botones ayudan a mantener el foco en el contenido más importante.

Botón de texto
A diferencia del anterior botón, este no contiene ese stroke que marca el ancho y largo de este, pues es un simple texto. Los usos más habituales son acciones que no queremos que se hagan por ejemplo si nos fijamos, muchas de las aplicaciones tienen un cerrar sesión con este tipo de botón.
Como los anteriores, su definición es idéntica pero cambiando el style por @style/Widget.MaterialComponents.Button.TextButton.
<com.google.android.material.button.MaterialButton android:id="@+id/textButton" style="@style/Widget.MaterialComponents.Button.TextButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Text button" />
El listener será igual que los anteriores.
textButton.setOnClickListener{ //La acción que quisiéramos hacer }
Si queremos añadir un icono tendremos que usar el estilo @style/Widget.MaterialComponents.Button.TextButton.Icon

Botón Text con icono
Y otra vez los atributos son los mismos.
Toggle Button
Se trata de un grupo de botones que tienen el mismo contenedor.

Botón Toggle
Lo he dejado para el final porque realmente no es un botón sino el contenedor de este.
<com.google.android.material.button.MaterialButtonToggleGroup android:id="@+id/toggleButton" android:layout_width="wrap_content" android:layout_height="wrap_content"> <com.google.android.material.button.MaterialButton android:id="@+id/button1" style="@style/Widget.MaterialComponents.Button.OutlinedButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 1" /> <com.google.android.material.button.MaterialButton android:id="@+id/button2" style="@style/Widget.MaterialComponents.Button.OutlinedButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 2" /> <com.google.android.material.button.MaterialButton android:id="@+id/button3" style="@style/Widget.MaterialComponents.Button.OutlinedButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 3" /> </com.google.android.material.button.MaterialButtonToggleGroup>
Si vemos el código anterior veremos que son los botones de siempre dentro de un MaterialButtonToggleGroup. En esta ocasión todos los botones son outlined, pues se recomiendan para los toggle button, pero puedes añadir el que quieras.
El listener que controla el toggle es algo distinto a los otros.
toggleButton.addOnButtonCheckedListener { toggleButton, checkedId, isChecked -> // Acciones del toggle }
En vez de usar el setOnClickListener usaremos addOnButtonCheckedListener que nos devolverá tres parámetros cuando sea pulsado. Estos tres parámetros serán el toggle button que hemos pulsado, la id del botón pulsado (recordemos que en el ejemplo anterior hay tres) y si está seleccionado o no. Toda esta información es devuelta porque es un componente bastante personalizable y esos parámetros nos ayudarán. Por ejemplo, isChecked es devuelvo porque podemos tener por defecto más de uno de los botones activados, y siempre que nosotros pulsemos uno nos avisará de como se queda.
Ese es el comportamiento por defecto del toggle, pero podemos cambiar a que solo pueda haber uno seleccionado con el atributo app:singleSelection.
Estilos para los botones
Después de todas las pruebas que hemos hecho tendremos un layout lleno de botones como esté.

Listado de botones trabajados durante el capítulo
Por muchos diseños que tengamos, quizás queremos hacer uno personalizado para nuestra app. Yo por ejemplo he creado este botón partiendo de un contained button.

Botón personalizado
El diseño de este botón se ha realizado añadiendo un stroke, un tamaño fijo de ancho (por lo que un texto largo se pone en dos líneas) y definí el mismo color para el texto.
<com.google.android.material.button.MaterialButton android:id="@+id/customButton" app:strokeWidth="3dp" android:textColor="@color/secondaryColor" app:strokeColor="@color/secondaryColor" android:layout_width="120dp" android:layout_height="wrap_content" android:text="Custom Button" />
Pero que pasa si este botón lo queremos usar por toda la app, pues que es bastante incómodo estar copiando y pegando el mismo código, además si luego decidimos cambiar alguna parte del botón debemos ir por todo el proyecto modificando todos los botones. Por ello pasaremos todos los atributos a un estilo. Iremos a styles.xml
<style name="CustomButton" parent="Widget.MaterialComponents.Button"> <item name="android:layout_height">wrap_content</item> <item name="android:layout_width">120dp</item> <item name="strokeColor">@color/secondaryColor</item> <item name="strokeWidth">3dp</item> <item name="android:textColor">@color/secondaryColor</item> </style>
Hemos creado un nuevo style con todos los atributos que le queríamos poner en nuestro botón, y de parent hemos puesto el estilo de los botones de material design.
Ahora nuestro botón quedaría así.
<com.google.android.material.button.MaterialButton android:id="@+id/customButton" style="@style/CustomButton" android:text="Custom Button" />
Como veis, incluso podemos meter en estilos los atributos obligatorios como layout_height y layout_width.
Para terminar, iremos a activity_main para añadir un botón para ir a nuestra página de botones. Usaremos el style previamente creado.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:gravity="center_horizontal" android:padding="20dp" android:background="@color/primaryLightColor" android:orientation="vertical" tools:context=".MainActivity"> <com.google.android.material.button.MaterialButton android:id="@+id/btnGoToButtons" style="@style/CustomButton" android:text="Botones" /> </LinearLayout>
Y debemos decirle al botón que la pulsarlo nos lleve a ButtonActivity. Así que vamos a MainActivity y en el método onCreate añadiremos un listener.
btnGoToButtons.setOnClickListener { startActivity( Intent( this, ButtonActivity::class.java ) ) }
Con esto ya tenemos nuestra parte de botones lista.

Pantalla principal
Como ya he dicho anteriormente, podéis encontrar el proyecto completo de material design en mi GitHub.
Si te está gustando el curso te pido que lo compartas para hacerlo llegar a más gente.
Continúa con el curso: Capítulo 26 – DatePicker en Kotlin
Te recuerdo que puedes seguirme en mis redes sociales en Aristi.Dev. Y si tienes dudas con este o cualquier otro artículo del blog únete al Discord de la comunidad y te ayudaremos.
Hola. Los floatingActionButton ¿son iguales a los demás? para qué se usan?
Exacto, son iguales que los botones normales pero por defecto están en la por encima de la pantalla en el lateral inferior derecho para acciones rápidas, pero el funcionamiento es el mismo.