MDC-101 Android: Conceptos básicos sobre componentes de Material (MDC) (Java)

1. Introducción

logo_components_color_2x_web_96dp.png

Los componentes de Material (MDC) ayudan a los desarrolladores a implementar Material Design. MDC, creado por un equipo de ingenieros y diseñadores de UX en Google, cuenta con decenas de componentes de IU atractivos y funcionales, y está disponible para Android, iOS, la Web y Flutter.material.io/develop.

¿Qué son Material Design y los componentes de Material para Android?

Material Design es un sistema para crear productos digitales atractivos y llamativos. Mediante la unión de estilo, desarrollo de la marca, interacción y movimiento en un conjunto coherente de principios y componentes, los equipos de productos pueden alcanzar su máximo potencial de diseño.

En el caso de las aplicaciones para Android, Material Components for Android (MDC Android) combina el diseño y la ingeniería con una biblioteca de componentes para crear coherencia en tu aplicación. A medida que evoluciona el sistema de Material Design, se actualizan estos componentes para garantizar una implementación coherente de píxeles perfectos y el cumplimiento de los estándares de desarrollo de frontend de Google. MDC también está disponible para la Web, iOS y Flutter.

En este codelab, compilarás una página de acceso usando varios de los componentes de MDC para Android.

Qué compilarás

Este codelab es el primero de 4 que te guiarán para que compiles una app llamada Shrine, una app de comercio electrónico para Android en la que se vende ropa y artículos para el hogar. Demostrará cómo puedes personalizar los componentes para que reflejen cualquier marca o estilo con MDC-Android.

En este codelab, crearás una página de acceso para Shrine que contiene lo siguiente:

  • Dos campos de texto: uno para ingresar un nombre de usuario y el otro para la contraseña
  • Dos botones, uno para "Cancelar" y una para "Siguiente"
  • El nombre de la app (Shine)
  • Una imagen del logotipo de Shrine

4cb0c218948144b4.png

Componentes de MDC para Android en este codelab

  • Campo de texto
  • Botón

Requisitos

  • Conocimientos básicos de desarrollo de Android
  • Android Studio (descárgalo aquí si todavía no lo tienes)
  • Un emulador o dispositivo Android (disponible a través de Android Studio)
  • El código de muestra (consulta el siguiente paso)

¿Cómo calificarías tu nivel de experiencia con la compilación de apps para Android?

Principiante Intermedio Avanzado .
.

2. Configura tu entorno de desarrollo

Inicia Android Studio

Cuando abras Android Studio, debería aparecer una ventana con el título "Welcome to Android Studio". Sin embargo, si es la primera vez que inicias Android Studio, sigue los pasos del asistente de configuración de Android Studio con los valores predeterminados. En este paso, descargar e instalar los archivos necesarios puede tardar varios minutos. Puedes permitir que se ejecute en segundo plano mientras realizas los pasos de la siguiente sección.

Descarga la app de inicio del codelab

La app de partida se encuentra en el directorio material-components-android-codelabs-101-starter/java.

… o clónalo desde GitHub

Para clonar este codelab desde GitHub, ejecuta los siguientes comandos:

git clone https://github.com/material-components/material-components-android-codelabs
cd material-components-android-codelabs/
git checkout 101-starter

Cómo cargar el código de inicio en Android Studio

  1. Una vez que finalice el asistente de configuración y aparezca la ventana Welcome to Android Studio, haz clic en Open an existing Android Studio project. Navega al directorio donde instalaste el código de muestra y selecciona java ->. santuario (o busca shrine en tu computadora) para abrir el proyecto de Shrine.
  2. Espera un momento para que Android Studio compile y sincronice el proyecto, como se muestra en los indicadores de actividad de la parte inferior de la ventana de Android Studio.
  3. En este punto, es posible que Android Studio genere algunos errores de compilación, ya que te faltan el SDK de Android o las herramientas de compilación, como se muestra más abajo. Sigue las instrucciones de Android Studio para instalar o actualizar estos elementos y sincronizar tu proyecto.

F5H6srsw_5xOPGFpKrm1RwgewatxA_HUbDI1PWoQUAoJcT6DpfBOkAYwq3S-2vUHvweUaFgAmG7BtUKkGouUbhTwXQh53qec8tO5eVecdlo7QIoLc8rNxFEBb8l7RlS-KzBbZOzVhA

Agrega dependencias del proyecto

El proyecto necesita una dependencia en la biblioteca de compatibilidad de MDC para Android. El código de muestra que descargaste ya debería tener esta dependencia en la lista, pero te recomendamos que realices los siguientes pasos para asegurarte.

  1. Navega al archivo build.gradle del módulo app y asegúrate de que el bloque dependencies incluya una dependencia en MDC para Android:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. Si es necesario, edita el archivo build.gradle para agregar las siguientes dependencias y sincronizar el proyecto (opcional).
dependencies {
    api 'com.google.android.material:material:1.1.0-alpha06'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:core:1.1.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test:runner:1.2.0-alpha05'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha05'
}

Cómo ejecutar la app de inicio

  1. Asegúrate de que la configuración de compilación ubicada a la izquierda del botón Run / Play sea app.
  2. Presiona el botón verde Run/Play para compilar y ejecutar la app.
  3. En la ventana Select Deployment Target, si ya tienes un dispositivo Android en la lista de dispositivos disponibles, ve al Paso 8. De lo contrario, haz clic en Create New Virtual Device.
  4. En la pantalla Select Hardware, selecciona un teléfono (por ejemplo, Pixel 2) y haz clic en Next.
  5. En la pantalla System Image, selecciona una versión reciente de Android, preferentemente, el nivel de API más alto. Si no está instalada, haz clic en el vínculo Download que aparece y completa la descarga.
  6. Haz clic en Next.
  7. En la pantalla Dispositivo virtual de Android (AVD), deja los parámetros de configuración como están y haz clic en Finalizar.
  8. Selecciona un dispositivo Android en el diálogo de destino de la implementación.
  9. Haz clic en Aceptar.
  10. Android Studio compila la app, la implementa y la abre automáticamente en el dispositivo de destino.

¡Listo! El código de partida para la página de acceso de Shrine debería estar ejecutándose en tu emulador. Deberías ver el nombre “Shrine”. y el logotipo de Shrine debajo.

e7ed014e84755811.png

Echemos un vistazo al código. Proporcionamos un framework de navegación Fragment simple en nuestro código de muestra para mostrar fragmentos y navegar entre ellos.

Abre MainActivity.java en el directorio shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.java.shrine. Debe contener lo siguiente:

MainActivity.java

package com.google.codelabs.mdc.java.shrine;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;

public class MainActivity extends AppCompatActivity implements NavigationHost {

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

       if (savedInstanceState == null) {
           getSupportFragmentManager()
                   .beginTransaction()
                   .add(R.id.container, new LoginFragment())
                   .commit();
       }
   }

   /**
    * Navigate to the given fragment.
    *
    * @param fragment       Fragment to navigate to.
    * @param addToBackstack Whether or not the current fragment should be added to the backstack.
    */
   @Override
   public void navigateTo(Fragment fragment, boolean addToBackstack) {
       FragmentTransaction transaction =
               getSupportFragmentManager()
                       .beginTransaction()
                       .replace(R.id.container, fragment);

       if (addToBackstack) {
           transaction.addToBackStack(null);
       }

       transaction.commit();
   }
}

Esta actividad muestra el archivo de diseño R.layout.shr_main_activity, definido en shr_main_activity.xml.

Puedes ver que en onCreate(), MainActivity.java inicia una transacción Fragment para mostrar el LoginFragment. LoginFragment. Eso es lo que modificaremos en este codelab. La actividad también implementa un método navigateTo(Fragment), definido en NavigationHost, que permite que cualquier fragmento navegue a uno diferente.

Comando + clic (o Control + clic) shr_main_activity en el archivo de actividad para abrir el archivo de diseño o navega hasta el archivo de diseño en app -> res -> layout -> shr_main_activity.xml.

shr_main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/container"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity" />

Aquí, vemos un <FrameLayout> simple que actúa como contenedor para cualquier fragmento que muestre la actividad. Abramos LoginFragment.java.

LoginFragment.java

package com.google.codelabs.mdc.java.shrine;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;

/**
* Fragment representing the login screen for Shrine.
*/
public class LoginFragment extends Fragment {

   @Override
   public View onCreateView(
           @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       // Inflate the layout for this fragment
       View view = inflater.inflate(R.layout.shr_login_fragment, container, false);

       // Snippet from "Navigate to the next Fragment" section goes here.

       return view;
   }

   // "isPasswordValid" from "Navigate to the next Fragment" section method goes here
}

LoginFragment aumenta el archivo de diseño shr_login_fragment y lo muestra en onCreateView(). Echemos un vistazo al archivo de diseño shr_login_fragment.xml para comprobar cómo es la página de acceso.

shr_login_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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:background="@color/loginPageBackgroundColor"
   tools:context=".LoginFragment">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:clipChildren="false"
       android:clipToPadding="false"
       android:orientation="vertical"
       android:padding="24dp"
       android:paddingTop="16dp">

       <ImageView
           android:layout_width="64dp"
           android:layout_height="64dp"
           android:layout_gravity="center_horizontal"
           android:layout_marginTop="48dp"
           android:layout_marginBottom="16dp"
           app:srcCompat="@drawable/shr_logo" />

       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="center_horizontal"
           android:layout_marginBottom="132dp"
           android:text="@string/shr_app_name"
           android:textAllCaps="true"
           android:textSize="16sp" />

       <!-- Snippet from "Add text fields" section goes here. -->

       <!-- Snippet from "Add buttons" section goes here. -->

   </LinearLayout>
</ScrollView>

Aquí, podemos ver un <LinearLayout> con un <ImageView> en la parte superior, que representa el "Shrine". logotipo.

Luego, hay una etiqueta <TextView> que representa "SHRINE" etiqueta. El texto de esta etiqueta es un recurso de cadenas con el nombre @string/shr_app_name. Si presionas Comando + clic (o Control + clic) en el nombre del recurso de strings o abres app -> res -> values -> strings.xml, podrás ver el archivo strings.xml en el que se definen los recursos de strings. Cuando se agreguen más recursos de cadenas en el futuro, se definirán aquí. Cada recurso de este archivo debe tener un prefijo shr_ para indicar que son parte de la app de Shrine.

Ahora que te familiarizaste con el código de partida, implementemos nuestro primer componente.

3. Agrega campos de texto

Para empezar, agregaremos dos campos de texto a nuestra página de acceso para que las personas ingresen su nombre de usuario y contraseña. Usaremos el componente de campo de texto de MDC, que incluye una funcionalidad integrada que muestra una etiqueta flotante y mensajes de error.

d83c47fb4aed3a82.png

Agrega el XML

En shr_login_fragment.xml, agrega dos elementos TextInputLayout con un elemento secundario TextInputEditText dentro de <LinearLayout>, debajo de "SHRINE". etiqueta <TextView>:

shr_login_fragment.xml

<com.google.android.material.textfield.TextInputLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/shr_hint_username">

   <com.google.android.material.textfield.TextInputEditText
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:inputType="text"
       android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
   android:id="@+id/password_text_input"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/shr_hint_password">

   <com.google.android.material.textfield.TextInputEditText
       android:id="@+id/password_edit_text"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>

El fragmento anterior representa dos campos de texto, cada uno formado por un elemento <TextInputLayout> y un elemento secundario <TextInputEditText>. El texto de la sugerencia para cada campo de texto se especifica en el atributo android:hint.

Incluimos dos recursos de cadenas nuevos para el campo de texto: @string/shr_hint_username y @string/shr_hint_password. Abre strings.xml para ver estos recursos de cadenas.

strings.xml

...
<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>
...

Agrega validación de entrada

Los componentes de TextInputLayout proporcionan una función integrada de comentarios sobre errores.

Para mostrar comentarios sobre el error, realiza los siguientes cambios en shr_login_fragment.xml:

  • Establece el atributo app:errorEnabled como verdadero en el elemento TextInputLayout Contraseña . Esto agregará padding adicional para el mensaje de error debajo del campo de texto.
  • Establece el atributo android:inputType en "textPassword" en el elemento Contraseña TextInputEditText. De esta manera, se ocultará el texto de entrada del campo de la contraseña.

Con estos cambios, los campos de texto en shr_login_fragment.xml deberían verse de la siguiente manera:

shr_login_fragment.xml

<com.google.android.material.textfield.TextInputLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/shr_hint_username">

   <com.google.android.material.textfield.TextInputEditText
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:inputType="text"
       android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
   android:id="@+id/password_text_input"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/shr_hint_password"
   app:errorEnabled="true">

   <com.google.android.material.textfield.TextInputEditText
       android:id="@+id/password_edit_text"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:inputType="textPassword"/>
</com.google.android.material.textfield.TextInputLayout>

Ahora prueba ejecutar la app. Deberías ver una página con dos campos de texto para “Username” y "Contraseña"!

Observa la animación de etiquetas flotantes:

333184b615aed4f7.gif

4. Cómo agregar botones

A continuación, agregaremos dos botones a nuestra página de acceso: "Cancel" y "Next". Usaremos el componente Botón de MDC, que viene con el emblemático efecto de ondas de tinta de Material Design integrado.

4cb0c218948144b4.png

Agrega el XML

En shr_login_fragment.xml, agrega un <RelativeLayout> a <LinearLayout>, debajo de los elementos TextInputLayout. Luego, agrega dos elementos <MaterialButton> a <RelativeLayout>.

El archivo en formato XML resultante debería verse de la siguiente manera:

shr_login_fragment.xml

<RelativeLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content">

   <com.google.android.material.button.MaterialButton
       android:id="@+id/next_button"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentEnd="true"
       android:layout_alignParentRight="true"
       android:text="@string/shr_button_next" />

   <com.google.android.material.button.MaterialButton
       android:id="@+id/cancel_button"
       style="@style/Widget.MaterialComponents.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginEnd="12dp"
       android:layout_marginRight="12dp"
       android:layout_toStartOf="@id/next_button"
       android:layout_toLeftOf="@id/next_button"
       android:text="@string/shr_button_cancel" />

</RelativeLayout>

Eso es todo. Cuando ejecutes la app, se mostrará una ondulación de tinta cuando presiones cada botón.

9dd162d65e4a92a2.gif

5. Navegar al siguiente fragmento

Por último, agregaremos código Java a LoginFragment.java para conectar nuestro “NEXT”. botón a otro fragmento. Notarás que cada uno de los componentes que agregamos a nuestro diseño tenía un id asignado. Usaremos esos id para hacer referencia a los componentes de nuestro código y agregar algunas verificaciones de errores y navegación.

Agreguemos un método booleano privado isPasswordValid en LoginFragment.java debajo de onCreateView(), con lógica para determinar si la contraseña es válida o no. A los efectos de esta demostración, nos aseguraremos de que la contraseña tenga al menos 8 caracteres:

LoginFragment.java

/*
   In reality, this will have more complex logic including, but not limited to, actual
   authentication of the username and password.
*/
private boolean isPasswordValid(@Nullable Editable text) {
   return text != null && text.length() >= 8;
}

A continuación, agrega un objeto de escucha de clics al panel que establece y borra el error según el método isPasswordValid() que acabamos de crear. En onCreateView(), este objeto de escucha de clics debe colocarse entre la línea del inflador y la línea de return view.

A continuación, agregaremos un objeto de escucha de claves a la contraseña TextInputEditText para escuchar los eventos clave que borrarán el error. Este objeto de escucha también debe usar isPasswordValid() para verificar si la contraseña es válida o no. Puedes agregar esto directamente debajo del objeto de escucha de clics en onCreateView().

Tu método onCreateView() debería verse de la siguiente manera:

LoginFragment.java

@Override
public View onCreateView(
       @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   // Inflate the layout for this fragment
   View view = inflater.inflate(R.layout.shr_login_fragment, container, false);
   final TextInputLayout passwordTextInput = view.findViewById(R.id.password_text_input);
   final TextInputEditText passwordEditText = view.findViewById(R.id.password_edit_text);
   MaterialButton nextButton = view.findViewById(R.id.next_button);

   // Set an error if the password is less than 8 characters.
   nextButton.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View view) {
           if (!isPasswordValid(passwordEditText.getText())) {
               passwordTextInput.setError(getString(R.string.shr_error_password));
           } else {
               passwordTextInput.setError(null); // Clear the error
           }
       }
   });

   // Clear the error once more than 8 characters are typed.
   passwordEditText.setOnKeyListener(new View.OnKeyListener() {
       @Override
       public boolean onKey(View view, int i, KeyEvent keyEvent) {
           if (isPasswordValid(passwordEditText.getText())) {
               passwordTextInput.setError(null); //Clear the error
           }
           return false;
       }
   });
   return view;
}            

Ahora podemos navegar a otro fragmento. Actualiza OnClickListener en onCreateView() para navegar a otro fragmento cuando se realice correctamente la validación de errores. Puedes hacerlo agregando la siguiente línea para navegar a ProductGridFragment en el caso else del objeto de escucha de clics:

LoginFragment.java

...
((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false); // Navigate to the next Fragment
...

Tu objeto de escucha de clics ahora debería verse de la siguiente manera:

LoginFragment.java

...
MaterialButton nextButton = view.findViewById(R.id.next_button);

// Set an error if the password is less than 8 characters.
nextButton.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
       if (!isPasswordValid(passwordEditText.getText())) {
           passwordTextInput.setError(getString(R.string.shr_error_password));
       } else {
           passwordTextInput.setError(null); // Clear the error
           ((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false); // Navigate to the next Fragment
       }
   }
});
...

Esta nueva línea de código llama al método navigateTo() desde MainActivity para navegar a un nuevo fragmento, ProductGridFragment. Actualmente, esta es una página vacía en la que trabajarás en MDC-102.

Ahora, compila la app. Presiona el botón Siguiente.

¡Lo lograste! Esta pantalla será el punto de partida de nuestro próximo codelab, en el que trabajarás en MDC-102.

6. Todo listo

Con lenguaje de marcado XML básico y aproximadamente 30 líneas de Java, los componentes de Material para la biblioteca de Android te ayudaron a crear una atractiva página de acceso que cumple con los lineamientos de Material Design y que también se ve y se comporta de manera coherente en todos los dispositivos.

Próximos pasos

El campo de texto y el botón son dos componentes principales de la biblioteca MDC para Android, pero hay muchos más. Puedes explorar el resto de los componentes de MDC para Android. Como alternativa, consulta MDC 102: Estructura y diseño de Material Design para obtener información sobre la barra superior de la app, la vista de tarjetas y el diseño de cuadrícula. Gracias por probar los componentes de Material. Esperamos que hayas disfrutado de este codelab.

Pude completar este codelab en una cantidad de tiempo y con un nivel de esfuerzo razonables

Totalmente de acuerdo De acuerdo Neutral En desacuerdo Totalmente en desacuerdo

Me gustaría seguir usando los componentes de Material en el futuro.

Muy de acuerdo De acuerdo Ni feliz ni triste En desacuerdo Muy en desacuerdo .
.