Uso práctico de Vistas y Layouts

En este apartado vamos a aprender a usar varios tipos de vistas y layouts desde un punto de vista práctico. También empezaremos a escribir código que será ejecutado cuando ocurran ciertos eventos:

Ejercicio: Un botón con gráficos personalizados

1.    Crea un nuevo proyecto con nombre: Mas Vistas. En la tercera ventana selecciona Empty Activity. Puedes dejar el resto de parámetros con los valores por defecto.

2.   Crea el fichero boton.xml en la carpeta res/drawable/. Para ello pulsa con el botón derecho sobre la carpeta res/drawable y selecciona ;New > Drawable Resource File. Introduce en el campo File name: <<boton>>  Reemplaza el código por el siguiente:

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

Este XML define un recurso único gráfico (drawable) que cambiará en función del estado del botón. El primer ítem define la imagen usada cuando se pulsa el botón, el segundo ítem define la imagen usada cuando el botón tiene el foco (cuando el botón está seleccionado con la rueda de desplazamiento o las teclas de dirección) y el tercero, la imagen en estado normal. Los gráficos, y en concreto los drawables, se estudiarán en el capítulo 4.

NOTA: El orden de los elementos <item> es importante. Cuando se va a dibujar se recorren los ítems en orden hasta que se cumpla una condición. Debido a que "boton_normal" es el último, sólo se aplica cuando las condiciones state_pressed y state_focused no se cumplen.

3.     Descarga  de http://www.androidcurso.com/index.php/119 las tres imágenes que aparecen a continuación. Para bajar cada imagen, pulsa sobre los nombres. Guardalos con el nombre de fichero se indica a continuación:

          boton_normal.jpg          boton_con_foco.jpg                boton_pulsado.jpg

4.   Selecciona los tres ficheros y cópialos en el portapapeles (Ctrl-C), selecciona la carpeta res/drawable/ del proyecto y pega los ficheros (Ctrl-V). Te preguntará si quieres copiarlos a la carpeta de recursos por defecto a alguna de recursos alternativos. Selecciona la primera opción.

5.     Abre el fichero res/layout/activity_main.xml.

6.     En la ventana Component Tree, elimina el TextView que encontrarás dentro del ConstraintLayout.

7.    Selecciona el ConstraintLayout. En la ventana de Attributes busca  el atributo BackgroundPulsal en el icono de la derecha y selecciona el recurso Color/android/white.

8.     Arrastra una vista de tipo ImageView dentro del ConstraintLayout. Selecciona el Drawable Boton.

9.     Situa el  ImageView en el centro. Para ello selecciona cada uno de sus puntos de anclaje arrastrando hasta el bonde al que mira. El resultado ha de ser:

10.  Introduce en el atributo onClick el valor sePulsa.

A continuación se muestra el código resultante para activity_main.xml:

2
<androidx.constraintlayout.widget.ConstraintLayout
        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"
        tools:context=".MainActivity" 
        android:background="@android:color/white">
    <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/button"
            android:background="@drawable/boton"
            android:onClick="sePulsa"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_marginBottom="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginEnd="8dp"
            app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout> 

11.  Abre el fichero MainActivity.java e introduce al final, antes de la última llave, el código:

public void sePulsa(View view){
   Toast.makeText(this, "Pulsado", Toast.LENGTH_SHORT).show();
} 
fun sePulsa(view: View) {
   Toast.makeText(this, "Pulsado", Toast.LENGTH_SHORT).show()
} 

NOTA:Pulsa Alt-Intro en Android Studio o Ctrl-Shift-O en Eclipse para que se añadan automáticamente los paquetes que faltan en la sección import.

El método anterior se ejecutará cuando se pulse el botón. A este tipo de métodos se los conoce como escuchadores de eventos (listeners). Este método se limita a lanzar un toast, es decir, un aviso que permanece cierto tiempo sobre la pantalla y luego desaparece. Los tres parámetros son: el contexto utilizado, que coincide con la actividad, el texto a mostrar y el tiempo que permanecerá este texto. Los conceptos de actividad y contexto se desarrollarán en el siguiente capítulo. 

12.  Ejecuta el proyecto y verifica el resultado.

Acceder y modificar las propiedades de las vistas por código

Ejercicio: Acceder y modificar las propiedades de las vistas por código

1.     Abre el Layout activity_main.xml creado en el ejercicio anterior.

2.     En la paleta de vistas, dentro de Text, busca Number (Decimal) y arrástralo arriba del botón rojo.

3.     Modifica algunos atributos de esta vista: hint = “Introduce un número”, ID = “entrada”

4.     En la paleta de vistas, dentro de Widgets, busca Button y arrástralo arriba del botón rojo.

5.     Modifica algunos atributos de esta vista: Haz que su anchura ocupe toda la pantalla, que su texto sea “0” y que su id sea “boton0".

6.     En la paleta de vistas, dentro de Widgets, busca TextView y arrástralo debajo del botón rojo.

7.   Modifica algunos atributos de esta vista: TextColor = #0000FF, Text = “”, Hint = “Resultado”, id= “salida”.

8.   Ajusta las restricciones de las vistas introducidas.

9.    Abre el fichero MainActivity. En Java vamos a añadir dos nuevas propiedades a la clase. Para ello copia el siguiente código al principio de la clase (antes del método onCreate()):

private EditText entrada;
private TextView salida; 
private lateinit var entrada: EditText
private lateinit var salida: TextView
 

NOTA: Recuerda pulsar Alt-Intro  para que se añadan los paquetes de las dos nuevas clases utilizadas.

 10.     En Java copia al final del método onCreate() las siguientes dos líneas: 

entrada = findViewById(R.id.entrada);
salida = findViewById(R.id.salida);
entrada = findViewById(R.id.entrada);
salida = findViewById(R.id.salida);

Como se explicó al principio del capítulo, las diferentes vistas defi­nidas en activity_main.xml, son creadas como objetos Java cuando se ejecuta setContentView(R.layout.main). Si queremos manipular algunos de estos objetos hemos de declarar las variables  (paso 9) y asignarles la referencia al objeto correspondiente (paso 10). Para ello, hay que introducir el atributo id en XML y utilizar el método findViewById(R.id.valor_en_atributo_id). Este método devuelve un objeto de la clase View.

11.  Introduce en el atributo onClick del botón con id boton0 el valor “sePulsa0”.  De esta manera, cuando se pulse sobre el botón se ejecutará el método sePulsa0(). Según la jerga de Java, diremos que este método es un escuchador del evento click que puede generar el objeto boton0.

12.  Añade el siguiente método al final de la clase MainActivity.

public void sePulsa0(View view){
   entrada.setText(entrada.getText()+"0");
} 
fun sePulsa0(view: View) {
   entrada?.setText(entrada?.text.toString() + "0")
}

Lo que hace es asignar como textos de entrada el resultado de concatenar al texto de entrada el carácter “0”.
NOTA: Si eres nuevo en Kotlin, te habrá extrañado el uso de ?. Lee la sección Tratamiento de null en Kotlin [1].

13.  Añade al botón con texto “0” el atributo tag = “0”.

14.  Modifica el método sePulsa0()de la siguiente forma:

Para seleccionar entre código Java y Kotlin
entrada.setText(entrada.getText()+(String)view.getTag()); 
entrada?.setText(entrada?.getText().toString() + view?.tag as String) 

El resultado obtenido es equivalente al anterior. En algunos casos será interesante utilizar un mismo método como escuchador de eventos de varias vistas. Podrás averiguar la vista que causó el evento, dado que esta es pasada como parámetro del método. En el ejemplo sabemos que en el atributo tag guardamos el carácter a insertar. El atributo tag puede ser usado libremente por el programador para almacenar un objeto de la clase Object (mas info ). (en la práctica podemos usar cualquier tipo de clase, dado que Object es la clase raíz de la que heredan todas las clases en Java).En nuestro caso hemos almacenado un objeto String, por lo que necesitamos una conversión de tipo.

 NOTA: Utiliza esta forma de trabajar en la práctica para no tener que crear un método onClick para cada botón.

15.     Modifica el código de sePulsa() con el siguiente código:

Para seleccionar entre código Java y Kotlin
salida.setText(String.valueOf(Float.parseFloat(
         entrada.getText().toString()) * 2.0));  
salida?.setText((java.lang.Float.parseFloat(
         entrada?.getText().toString()) * 2.0).toString())  

 En este código el valor de entrada es convertido en Float, multiplicado por dos y convertido en String para ser asignado a salida.

16.  Ejecuta el proyecto y verifica el resultado. 
NOTA: En este ejercicio no se ha realizado la verificación de que los datos introducidos por el usuario. Has de tener introducir datos válidos y en el orden adecuado. 

Preguntas de repaso: Uso práctico de Vistas


[1] http://www.androidcurso.com/index.php/922