mayo 20, 2024

FindViewById (Diseño Kotlin 17)

En esta clase vamos a comenzar una parte básica: comunicar la vista con la actividad. Es decir, vamos a crear eventos para los elementos de nuestras vistas. Por ejemplo, que podamos dar click sobre un botón y se abra un mensaje, o que lleve a otra página… en definitiva, comenzar a darle funcionalidad a nuestras aplicaciones.

Para empezar vamos a ver cómo podemos hacer para vincular elementos de la vista con la actividad. Existen dos formas básicas. La primera, y la que atañe a esta clase: FindViewById. La segunda forma, más eficiente y que veremos en la clase siguiente, View Binding.

En el ejemplo de esta clase, para ver cómo funciona FindViewById, haremos que, cuando hagamos click sobre el botón flotante de nuestra aplicación, cambie de lugar respecto a la barra de navegación. Es decir, queremos dar click sobre el botón y que al hacerlo su posición cambie de un lado a otro a partir de una animación básica.

Preparación del código para la clase:

Lo que vamos a ver primero y rápidamente es el código del que vamos a partir para este ejemplo con FindViewById. Para que no tengas que volver a clases anteriores, a continuación tienes el código que ya creamos y sobre el que trabajaremos esta clase.

En nuestro archivo activity_scrolling.xml ahora mismo tenemos:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:fitsSystemWindows="true"
    tools:context=".ScrollingActivity">

    <include layout="@layout/content_scrolling" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Tras el include vamos a añadir el siguiente código, que es el que creamos para el el BottomAppBar y Floating Action Button:

<com.google.android.material.bottomappbar.BottomAppBar
        android:id="@+id/barraNavevagion"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        app:navigationIcon="@drawable/icono_menu"
        app:menu="@menu/menu_scrolling"
        app:hideOnScroll="true"
        style="@style/Widget.MaterialComponents.BottomAppBar.Colored"/>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/bFlotante1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/icono_info"
        android:contentDescription="@string/obtener_informaci_n"
        app:layout_anchor="@id/barraNavevagion"/>

De esta manera, el código completo del que partimos en activity_scrolling.xml para esta clase es:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:fitsSystemWindows="true"
    tools:context=".ScrollingActivity">

    <include layout="@layout/content_scrolling" />


    <com.google.android.material.bottomappbar.BottomAppBar
        android:id="@+id/barraNavevagion"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        app:navigationIcon="@drawable/icono_menu"
        app:menu="@menu/menu_scrolling"
        app:hideOnScroll="true"
        style="@style/Widget.MaterialComponents.BottomAppBar.Colored"/>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/bFlotante1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/icono_info"
        android:contentDescription="@string/obtener_informaci_n"
        app:layout_anchor="@id/barraNavevagion"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Así se vería:

activity scrolling

Ya estamos preparados para iniciar la clase.


Animando un elemento de la vista, desde la actividad

Lo primero que haremos será darle una pequeña animación al botón flotante (FloatingActionButton) respecto a su posición en BottomAppBar. Lo que queremos conseguir es que, cuando hagamos click sobre el botón flotante (FloatingActionButton) que sale en medio de la barra (BottomAppBar), cambie su ubicación y se coloque en la derecha de la barra, y viceversa.

Para hacer esto, a nuestro componente BottomAppBar le añadiremos la propiedad fabAnimationMode con el valor «escale» (al final de la clase veremos la otra opción de valor, que es «slide«):

app:fabAnimationMode="scale"

Seguidamente lo que queremos hacer es comenzar a comunicar la actividad con nuestra vista para empezar a darle funcionalidad, por muy básica que sea. Nos iremos a nuestro archivo ScrollingActivity.kt (dentro de la carpeta java). Este es el código que tenemos por defecto, ya que no hemos tocado nada hasta ahora:

package com.codigokotlin.android.componentes

    import android.os.Bundle
    import com.google.android.material.appbar.CollapsingToolbarLayout
    import com.google.android.material.floatingactionbutton.FloatingActionButton
    import com.google.android.material.snackbar.Snackbar
    import androidx.appcompat.app.AppCompatActivity
    import android.view.Menu
    import android.view.MenuItem

    class ScrollingActivity : AppCompatActivity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_scrolling)
        }

        override fun onCreateOptionsMenu(menu: Menu): Boolean {
            // Inflate the menu; this adds items to the action bar if it is present.
            menuInflater.inflate(R.menu.menu_scrolling, menu)
            return true
        }

        override fun onOptionsItemSelected(item: MenuItem): Boolean {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.

            return when (item.itemId) {
                R.id.action_settings -> true
                else -> super.onOptionsItemSelected(item)
            }
        }
    }

Ahora estamos en la actividad, y queremos acceder a la vista (los elementos que tenemos creados). Para hacerlo, tenemos dos formas, mediante findViewById (lo vemos en esta clase) y mediante View Binding (lo vemos en la clase siguiente).


Acceder a elementos mediante findViewById

Situándonos en el método onCreate de la actividad, accederemos a los elementos de nuestra vista mediante findViewById:

findViewById<>()

Los parámetros que necesitamos introducir son:

findViewById <TIPO DE COMPONENTE>(R.id.IDENTIFICADOR)

Así, para acceder a nuestro elemento FloatingActionButton, que tenemos con id «bFlotante1», en el método onCreate (después de las dos líneas ya existentes) agregaríamos:

findViewById<FloatingActionButton>(R.id.bFlotante1)

Este sería el método onCreate que tenemos:

override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_scrolling)

            findViewById<FloatingActionButton>(R.id.bFlotante1)

        }

De esta manera ya tendríamos acceso al componente de id bFlotante1 y tipo FloatingActionButton desde nuestra actividad.

Si después de haber accedido al componente añadiésemos un punto, podríamos tener acceso a sus propiedades y métodos:

propiedades metodos


Añadiendo un listener

Para ver un ejemplo, vamos a hacer que, al dar click en el FloatingActionButton, cambie de posición. Es decir, si está en el centro de la barra, se coloque en la derecha. Y si hacemos click sobre el botón estando a la derecha, se coloque en el centro.

Para empezar añadiremos un listener (setOnClickListener) que se ejecutará cuando hagamos click sobre el FloatingActionButton:

 findViewById<FloatingActionButton>(R.id.bFlotante1).setOnClickListener{
                
            }

Todo lo que escribamos ahora entre los {} se ejecutará cada vez que hagamos click sobre el FloatingActionButton que hemos enlazado con findViewById.

El evento de click, setOnClickListener, lo veremos con detalle tras ver findViewById y View Binding, en la clase número 19.

Primero, con una sentencia if, vamos a comprobar si la posición del botón en la barra es centrada. Para ello también necesitaremos acceder al elemento BottomAppBar, de la misma manera que con el FloatingActionButton:

findViewById<BottomAppBar>(R.id.barraNavevagion)

Posible error en BottomAppBar

Si te remarcase en rojo «BottomAppBar«, como se ve en la siguiente imagen…

error bottomappbar

es muy probable que sea debido a que no tenemeos importada la librería. Para ello colocaríamos el cursor del ratón sobre el color rojo y daríamos click en «Import»:

importar error

Ahora, para compobar si el elemento al que acabamos de acceder está centrado respecto a la barra, utilizaríamos fabAlignmentMode de la siguiente manera (ya dentro del if para hacer la comprobación):

if(findViewById<BottomAppBar>(R.id.barraNavevagion).fabAlignmentMode == BottomAppBar.FAB_ALIGNMENT_MODE_CENTER){
                    
                }else{
                    
                }

En este if estamos comprobando si la posición del elemento de id barraNavevagion es centrada. En caso de serlo, lo que haremos será que el propio elemento se coloque en la parte final (derecha):

findViewById<BottomAppBar>(R.id.barraNavevagion).fabAlignmentMode = BottomAppBar.FAB_ALIGNMENT_MODE_END

Para el else, es decir, en caso de que no estuviese el botón en el centro, especificaremos que queremos que se coloque en el centro:

findViewById<BottomAppBar>(R.id.barraNavevagion).fabAlignmentMode = BottomAppBar.FAB_ALIGNMENT_MODE_CENTER

Así sería el «listener» completo cuando hacemos click en el botón flotante:

findViewById<FloatingActionButton>(R.id.bFlotante1).setOnClickListener{

                if(findViewById<BottomAppBar>(R.id.barraNavevagion).fabAlignmentMode == BottomAppBar.FAB_ALIGNMENT_MODE_CENTER){
                    findViewById<BottomAppBar>(R.id.barraNavevagion).fabAlignmentMode = BottomAppBar.FAB_ALIGNMENT_MODE_END
                }else{
                    findViewById<BottomAppBar>(R.id.barraNavevagion).fabAlignmentMode = BottomAppBar.FAB_ALIGNMENT_MODE_CENTER
                }

            }

Si ejecutamos la aplicación en el emulador y hacemos click sobre el botón flotante, podremos ver cómo cambia su posición en la barra hacia la derecha. Y si volvemos a clicarlo, se vuelve al centro.

posicion boton


Cambiando el tipo de animación

Cuando hacemos click en el botón y pasa de un lado hacia otro, lo hace como a «saltos». Esto es debido a que en nuestro archivo activity_scrolling.xml, al principio de esta clase habíamos añadido al elemento BottomAppBar la propiedad fabAnimationMode y le dimos el valor «scale».

Si ahora cambiamos ese valor «scale» por «slide», que es la otra opción, y volvemos a ejecutar la aplicación en el emulador, podremos ver el cambio de animación al clicar en el botón flotante. Ahora, el botón se deslizará suavemente de un lado hacia el otro.

app:fabAnimationMode="slide"

Esto queda a gusto de cada cuál, y dependiendo el objetivo de nuestra aplicación, podríamos utilizar un tipo u otro de animación.


Así de fácil sería enlazar, o vincular, uno o varios elementos de nuestra vista con la actividad, utilizando FindViewById.

En la próxima clase veremos la otra forma que existe de vincular la vista con la actividad: mediante View Binding. View Binding es mejor opción que FindViewById. El resultado de ambas formas es el mismo, sin embargo View Binding nos va a proporcionar muchas más ventajas, como ahorro de código, ahorro de errores y otras facilidades básicas que veremos en la próxima clase.

Enlaces relacionados (siguiente clase):
View Binding (Diseño Kotlin 18).






2 comentarios en «FindViewById (Diseño Kotlin 17)»

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *