Ejercicio de diseño: de LinearLayout a ConstraintLayout
Hasta ahora hemos visto diversos conceptos relativos al diseño y la distribución de elementos en la pantalla, pero la mejor manera de familiarizarse con ellos es utilizarlos y trastear con el editor de diseño. Por ello, en esta entrada vamos a practicar con el diseño de una aplicación, y concretamente vamos a transformar una aplicación diseñada a base de LinearLayout para convertir el contenedor principal de elementos en un ConstraintLayout (ver Fundamentos de Android: Diseño con ConstraintLayout) y que el diseño sea más limpio reduciendo la jerarquía de elementos anidados. Además vamos utilizar otros conceptos conocidos como cadenas de elementos (chain), elementos de imagen, recursos de distinto tipo (texto, dimensiones, colores, estilos, etc.) y algunos más.
Vamos a partir del proyecto ControlAcceso, que hemos ido retocando en las últimas entradas, tal como lo dejamos en Data Binding para mostrar datos. Concretamente, en esa entrada el código de los archivos de diseño quedó así:
<!--- activity_main.xml --> <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <LinearLayout android:id="@+id/linearLayout" style="@style/estilo_linear" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/user_txt" style="@style/estilo_texto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/margen_txt_end1" android:text="@string/usuario" /> <EditText android:id="@+id/user_input" style="@style/estilo_texto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="@string/usuario" android:inputType="textPersonName" /> </LinearLayout> <LinearLayout android:id="@+id/linearLayout2" style="@style/estilo_linear" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="horizontal"> <TextView android:id="@+id/pass_txt" style="@style/estilo_texto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/margen_txt_end2" android:text="@string/contraseña" /> <EditText android:id="@+id/pass_input" style="@style/estilo_texto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="@string/contraseña" android:inputType="textPassword" /> </LinearLayout> <Button android:id="@+id/entrar_btn" style="@style/Widget.AppCompat.Button.Colored" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="@dimen/margen_linea" android:text="@string/btn_entrar" /> </LinearLayout> </layout>
<!--- activity_login_check.xml --> <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="usuario" type="com.android.controlacceso.Usuario" /> </data> <LinearLayout style="@style/estilo_linear" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".LoginCheck"> <TextView android:id="@+id/acceso_txt" style="@style/estilo_texto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/margen_linea" android:text="@string/login_check" android:textAlignment="center" /> <TextView android:id="@+id/login_txt" style="@style/estilo_texto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/margen_linea" android:text="@={usuario.nombre}" android:textAlignment="center" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:id="@+id/pass_txt" style="@style/estilo_texto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:background="@null" android:ems="10" android:enabled="false" android:inputType="textPassword" android:text="@={usuario.pass}" android:textAlignment="center" /> <CheckBox android:id="@+id/checkBox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/btn_ver" /> </LinearLayout> <Button android:id="@+id/button_cerrar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/margen_linea" android:text="@string/cerrar" /> </LinearLayout> </layout>
En las siguientes imágenes se aprecia el editor de diseño de ambos archivos después de la conversión del LinearLayout a un ConstraintLayout, observándose en el árbol de componentes los elementos de diseño utilizados, y finalmente unas capturas de pantalla de la aplicación en funcionamiento:
Como se supone que ya se conocen los métodos de aplicación de las técnicas utilizadas (en caso contrario revisar las entradas correspondientes), solo se expone el resultado final del código:
<!--- activity_main.xml --> <?xml version="1.0" encoding="utf-8"?> <layout 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"> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/constraint_layout" style="@style/estilo_constraint" tools:context=".MainActivity"> <TextView android:id="@+id/textView" style="@style/estilo_titulo" android:text="@string/acceso" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <ImageView android:id="@+id/imageView" style="@style/estilo_imagen" android:contentDescription="@string/imagen_candado" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" app:srcCompat="@android:drawable/ic_secure" /> <TextView android:id="@+id/user_txt" style="@style/estilo_texto" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/margen16" android:text="@string/usuario" app:layout_constraintBaseline_toBaselineOf="@+id/user_input" app:layout_constraintEnd_toStartOf="@+id/user_input" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintStart_toStartOf="parent" /> <EditText android:id="@+id/user_input" style="@style/estilo_texto" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="@dimen/margen32" android:layout_marginEnd="@dimen/margen16" android:ems="10" android:hint="@string/usuario" android:inputType="textPersonName" android:textAlignment="textEnd" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/user_txt" app:layout_constraintTop_toBottomOf="@+id/imageView" /> <TextView android:id="@+id/pass_txt" style="@style/estilo_texto" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/margen16" android:text="@string/contraseña" app:layout_constraintBaseline_toBaselineOf="@+id/pass_input" app:layout_constraintEnd_toStartOf="@+id/pass_input" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" /> <EditText android:id="@+id/pass_input" style="@style/estilo_texto" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="@dimen/margen32" android:layout_marginEnd="@dimen/margen16" android:ems="10" android:hint="@string/contraseña" android:inputType="textPassword" android:textAlignment="textEnd" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/pass_txt" app:layout_constraintTop_toBottomOf="@+id/user_input" /> <Button android:id="@+id/entrar_btn" style="@style/Widget.AppCompat.Button.Colored" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginBottom="@dimen/margen32" android:text="@string/sesion_inicio" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
<!--- activity_login_check.xml --> <?xml version="1.0" encoding="utf-8"?> <layout 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"> <data> <variable name="usuario" type="com.android.controlacceso.Usuario" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/constraint_layout" style="@style/estilo_constraint" android:background="@color/fondo" android:padding="@dimen/padding16" tools:context=".LoginCheck"> <TextView android:id="@+id/acceso_txt" style="@style/estilo_titulo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/login_check" android:textAlignment="center" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <ImageView android:id="@+id/imageView2" style="@style/estilo_imagen" android:contentDescription="@string/imagen_candado_abierto" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/acceso_txt" app:srcCompat="@android:drawable/ic_partial_secure" /> <TextView android:id="@+id/login_txt" style="@style/estilo_texto" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/margen32" android:layout_marginTop="@dimen/margen_linea" android:layout_marginEnd="@dimen/margen32" android:text="@={usuario.nombre}" android:textAlignment="center" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/imageView2" /> <EditText android:id="@+id/pass_txt" style="@style/estilo_texto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/margen32" android:layout_weight="1" android:background="@null" android:ems="10" android:enabled="false" android:hint="@string/code_pass" android:inputType="textPassword" android:text="@={usuario.pass}" android:textAlignment="center" app:layout_constraintBaseline_toBaselineOf="@+id/checkBox" app:layout_constraintEnd_toStartOf="@+id/checkBox" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" /> <CheckBox android:id="@+id/checkBox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/margen32" android:layout_marginEnd="@dimen/margen8" android:layout_weight="1" android:text="@string/btn_ver" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toEndOf="@+id/pass_txt" app:layout_constraintTop_toBottomOf="@+id/login_txt" /> <Button android:id="@+id/button_cerrar" style="@style/Widget.AppCompat.Button.Colored" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/margen32" android:layout_marginEnd="@dimen/margen32" android:layout_marginBottom="@dimen/margen32" android:text="@string/cerrar" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
Por otra parte, hemos aprovechado estos cambios de diseño para mejorar el código del controlador del CheckBox en el archivo de la actividad LoginCheck, que estaba de esta manera:
binding.checkBox.setOnClickListener(View.OnClickListener { if (binding.checkBox.isChecked) { binding.passTxt.inputType = InputType.TYPE_CLASS_TEXT } else { binding.passTxt.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD } })para dejarlo así (lo que hace innecesaria la instrucción de importación import android.view.View):
binding.checkBox.setOnClickListener { if (binding.checkBox.isChecked) { binding.passTxt.inputType = InputType.TYPE_CLASS_TEXT } else { binding.passTxt.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD } }
Comentarios
Publicar un comentario