MDC-104 Android: Componentes avanzados de Material (Java)

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

En el codelab MDC-103, personalizaste el color, la elevación y la tipografía de los componentes de Material (MDC) para diseñar tu app.

Los componentes del sistema de Material Design realizan un conjunto de tareas predefinidas y tienen determinadas características, como botones. Sin embargo, un botón representa más que una forma de realizar acciones solicitadas por el usuario; también es una expresión visual de forma, tamaño y color que le permite al usuario entender su interactividad y que sucederá algo cuando lo toque o haga clic en él.

En los lineamientos de Material Design se describen los componentes desde el punto de vista de un diseñador. Además, se detallan una gran variedad de funciones básicas que están disponibles en diferentes plataformas, como los elementos anatómicos que conforman cada componente. Por ejemplo, un fondo contiene una capa posterior y su contenido, la capa frontal y su contenido, reglas de movimiento y opciones de visualización. Todos estos componentes se pueden personalizar según las necesidades de cada app, caso de uso y contenido. En su mayoría, estas partes son funciones, controles y vistas tradicionales del SDK de tu plataforma.

Si bien en los lineamientos de Material Design se mencionan muchos componentes, no todos son candidatos apropiados para el código reutilizable y, por lo tanto, no los encontrarás en MDC. Puedes crear estas experiencias por tu cuenta a fin de obtener un estilo personalizado para tu app, usando código tradicional.

Qué compilarás

En este codelab, agregarás un fondo a Shrine. Filtrará los productos que se muestran en la cuadrícula asimétrica por categoría. Usarás lo siguiente:

  • Forma
  • Movimiento
  • Clases tradicionales del SDK de Android

Componentes de MDC-Android en este codelab

  • Forma

Requisitos

  • Conocimientos básicos sobre el desarrollo para Android
  • Android Studio (descárgala aquí si aún 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

¿Vienes de MDC-103?

Si completaste MDC-103, tu código debería estar listo para este codelab. Avanza al paso 3.

¿Empiezas de cero?

Descarga la app de inicio del codelab

Descargar app de inicio

La app de inicio se encuentra en el directorio material-components-android-codelabs-104-starter/java. Asegúrate de usar cd en ese directorio antes de comenzar.

… 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 104-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 en el que 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.

Cómo agregar dependencias de proyectos

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

  1. Navega hasta el 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. (Opcional) Si es necesario, edita el archivo build.gradle para agregar las siguientes dependencias y sincronizar el proyecto.
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. Haga clic en Siguiente.
  7. En la pantalla Dispositivo virtual de Android (AVD), deja la configuración como está y haz clic en Finalizar.
  8. Selecciona un dispositivo Android en el cuadro de diálogo de destino de la implementación.
  9. Haga clic en OK.
  10. Android Studio compila la app, la implementa y la abre automáticamente en el dispositivo de destino.

¡Listo! Deberías ver la app de Shrine en ejecución en tu dispositivo.

Un fondo es la superficie posterior más lejana de una app, que aparece detrás de todos los demás contenido y componentes. Está compuesta por dos plataformas: una posterior (que muestra acciones y filtros) y una frontal (que muestra contenido). Puedes usar un fondo para mostrar información y acciones interactivas, como filtros de contenido o navegación.

Cómo ocultar el contenido de la cuadrícula

En shr_product_grid_fragment.xml, agrega el atributo android:visibility="gone" a tu NestedScrollView para quitar de forma temporal el contenido del producto:

shr_product_grid_fragment.xml

<androidx.core.widget.NestedScrollView
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginTop="56dp"
   android:background="@color/productGridBackgroundColor"
   android:elevation="8dp"
   android:visibility="gone"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

Instalaremos un fondo en esta región. Para que no aparezca una división entre la barra superior de la app y el contenido del menú que aparece en el fondo, haremos que el fondo sea del mismo color que la barra superior de la app.

En shr_product_grid_fragment.xml, agrega lo siguiente como primer elemento en tu FrameLayout raíz, antes del AppBarLayout:

shr_product_grid_fragment.xml

<LinearLayout
   style="@style/Widget.Shrine.Backdrop"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:gravity="center_horizontal"
   android:orientation="vertical"
   android:paddingTop="100dp"
   android:paddingBottom="100dp">

</LinearLayout>

En styles.xml, agrega el siguiente código:

styles.xml

<style name="Widget.Shrine.Backdrop" parent="">
   <item name="android:background">?attr/colorAccent</item>
</style>

¡Bien hecho! Agregaste un fondo atractivo a la IU del santuario. A continuación, agregaremos un menú.

Agrega el menú

Un menú es, básicamente, una lista de botones de texto. Agregaremos una aquí.

Crea un nuevo diseño llamado shr_backdrop.xml en tu directorio res -> layout y agrega lo siguiente:

shr_backdrop.xml.

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_featured_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_apartment_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_accessories_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_shoes_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_tops_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_bottoms_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_dresses_label" />

   <View
       android:layout_width="56dp"
       android:layout_height="1dp"
       android:layout_margin="16dp"
       android:background="?android:attr/textColorPrimary" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_account_label" />

</merge>

Además, agrega esta lista al LinearLayout que acabas de agregar en shr_product_grid_fragment.xml con una etiqueta <include>:

shr_product_grid_fragment.xml

<LinearLayout
   style="@style/Widget.Shrine.Backdrop"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:gravity="center_horizontal"
   android:orientation="vertical"
   android:paddingTop="88dp">

   <include layout="@layout/shr_backdrop" />
</LinearLayout>

Compila y ejecuta. La pantalla principal debería verse de la siguiente manera:

El fondo está listo. Volvamos al contenido que ocultamos anteriormente.

Antes de realizar cambios en Shrine en este codelab, el contenido principal de sus productos se encontraba en la superficie posterior. Cuando se agrega un fondo, ahora se enfatiza este contenido porque aparece frente a ese fondo.

Cómo agregar una capa nueva

Debemos volver a mostrar la capa de cuadrícula del producto. Quita el atributo android:visibility="gone" de tu NestedScrollView:

shr_product_grid_fragment.xml

<androidx.core.widget.NestedScrollView
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginTop="56dp"
   android:background="@color/productGridBackgroundColor"
   android:elevation="8dp"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

Veamos la capa frontal con una muesca en la esquina superior izquierda. En Material Design, este tipo de personalización se conoce como una forma. Las superficies de Material se pueden mostrar en diferentes formas. Estas formas agregan énfasis y estilo a las superficies y se pueden usar para expresar la marca. Las formas de los materiales pueden tener esquinas y bordes curvos o angulados, y la cantidad de lados que quieras. Además, pueden ser simétricas o irregulares.

Cómo agregar una forma

Modifica la forma de la cuadrícula. Proporcionamos un fondo de forma personalizada, pero la forma solo se muestra correctamente en Android Marshmallow y versiones posteriores. Podemos configurar el fondo shr_product_grid_background_shape de tu NestedScrollView solo para Android Marshmallow y versiones posteriores. Primero, agrega un elemento id a tu NestedScrollView para que podamos hacer referencia a él en el código, de la siguiente manera:

shr_product_grid_fragment.xml

<androidx.core.widget.NestedScrollView
   android:id="@+id/product_grid"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginTop="56dp"
   android:background="@color/productGridBackgroundColor"
   android:elevation="8dp"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

Luego, configura el fondo de manera programática en ProductGridFragment.java. Agrega la siguiente lógica para configurar el fondo al final de onCreateView(), justo antes de la sentencia de devolución:

ProductGridFragment.java

// Set cut corner background for API 23+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    view.findViewById(R.id.product_grid).setBackgroundResource(R.drawable.shr_product_grid_background_shape);
}

Por último, actualizaremos el recurso de color productGridBackgroundColor (también utilizado por el fondo de forma personalizada) de la siguiente manera:

colors.xml

<color name="productGridBackgroundColor">#FFFBFA</color>

Compila y ejecuta:

Le dimos a Shrine una forma personalizada con su superficie principal. Debido a la elevación de la superficie, los usuarios pueden ver que hay algo detrás de la capa blanca frontal. Agreguemos movimiento para que los usuarios puedan ver qué hay allí: el menú.

El movimiento permite darle vida a tu app. El movimiento puede ser amplio y dramático, sutil y mínimo, o bien un efecto intermedio. El tipo de movimiento que uses debe ser adecuado para la situación. El movimiento que se aplica a acciones regulares repetidas debe ser pequeño y sutil, por lo que no lleva mucho tiempo seguido. Otras situaciones, como la primera vez que el usuario abre una app, pueden resultar más llamativas y pueden enseñarle a usar la app.

Agrega movimiento de revelación al botón de menú

El movimiento es la forma que se mueve el frente hacia abajo. Ya te proporcionamos un objeto de escucha de clics que ejecutará la animación de traducción de la hoja en NavigationIconClickListener.java. Podemos configurar este objeto de escucha de clics dentro del método setupToolbar() de ProductGridFragment.java:

ProductGridFragment.java

toolbar.setNavigationOnClickListener(new NavigationIconClickListener(getContext(), view.findViewById(R.id.product_grid)));

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

ProductGridFragment.java

private void setUpToolbar(View view) {
   Toolbar toolbar = view.findViewById(R.id.app_bar);
   AppCompatActivity activity = (AppCompatActivity) getActivity();
   if (activity != null) {
       activity.setSupportActionBar(toolbar);
   }

   toolbar.setNavigationOnClickListener(new NavigationIconClickListener(getContext(), view.findViewById(R.id.product_grid)));
}

Compila y ejecuta. Presiona el botón de menú:

Si vuelves a presionar el ícono de menú de navegación, se debería ocultar el menú.

Ajuste de movimiento de la capa frontal

El movimiento es una excelente manera de expresar tu marca. Veamos cómo es la animación de revelación con una curva de tiempo diferente.

Actualiza tu código en setupToolbar() en ProductGridFragment.java para pasar un interpolador a tu objeto de escucha de clics del ícono de navegación, de la siguiente manera:

ProductGridFragment.java

private void setUpToolbar(View view) {
   Toolbar toolbar = view.findViewById(R.id.app_bar);
   AppCompatActivity activity = (AppCompatActivity) getActivity();
   if (activity != null) {
       activity.setSupportActionBar(toolbar);
   }

   toolbar.setNavigationOnClickListener(new NavigationIconClickListener(
           getContext(),
           view.findViewById(R.id.product_grid),
           new AccelerateDecelerateInterpolator()));
}

Esto genera un efecto diferente, ¿no?

La iconografía de la marca también se extiende a los íconos conocidos. Personalizarás el ícono de revelación y lo combinarás con el título para crear una apariencia de marca única.

Cambia el ícono del botón de menú

Cambia el botón de menú para que se muestre un ícono que incluye un diseño de diamante. Actualiza tu barra de herramientas de shr_product_grid_fragment.xml para usar el nuevo ícono de marca que proporcionamos (shr_branded_menu) y configura los atributos app:contentInsetStart y android:padding para que la barra de herramientas coincida mejor con las especificaciones de tu diseñador:

shr_product_grid_fragment.xml

<androidx.appcompat.widget.Toolbar
   android:id="@+id/app_bar"
   style="@style/Widget.Shrine.Toolbar"
   android:layout_width="match_parent"
   android:layout_height="?attr/actionBarSize"
   android:paddingStart="12dp"
   android:paddingLeft="12dp"
   android:paddingEnd="12dp"
   android:paddingRight="12dp"
   app:contentInsetStart="0dp"
   app:navigationIcon="@drawable/shr_branded_menu"
   app:title="@string/shr_app_name" />

Actualiza el objeto de escucha de clics otra vez en setupToolbar() en ProductGridFragment.java para incorporar los elementos de diseño de la barra de herramientas cuando se abre el menú y cuando se cierra, de la siguiente manera:

ProductGridFragment.java

private void setUpToolbar(View view) {
   Toolbar toolbar = view.findViewById(R.id.app_bar);
   AppCompatActivity activity = (AppCompatActivity) getActivity();
   if (activity != null) {
       activity.setSupportActionBar(toolbar);
   }

   toolbar.setNavigationOnClickListener(new NavigationIconClickListener(
           getContext(),
           view.findViewById(R.id.product_grid),
           new AccelerateDecelerateInterpolator(),
           getContext().getResources().getDrawable(R.drawable.shr_branded_menu), // Menu open icon
           getContext().getResources().getDrawable(R.drawable.shr_close_menu))); // Menu close icon
}

Compila y ejecuta:

¡Muy bien! Cuando se puede revelar el fondo, se muestra el ícono del menú de diamante. Cuando el menú se puede ocultar, se muestra un ícono de cierre.

En el transcurso de estos cuatro codelabs, viste cómo usar componentes de Material para crear experiencias del usuario elegantes y únicas que expresen la personalidad y el estilo de una marca.

Próximos pasos

Este codelab, MDC-104, completa la secuencia de codelabs actual. Puedes explorar aún más componentes de MDC-Android visitando el catálogo de widgets de Android.

Para aumentar el desafío con este codelab, modifica la aplicación Shrine a fin de cambiar las imágenes del producto que se muestran cuando se selecciona una categoría en el menú de fondo.

Para obtener información sobre cómo conectar esta app a Firebase para obtener un backend que funcione, consulta el Codelab de Firebase para Android.

Pude completar este codelab con una cantidad de tiempo y 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 Aceptar Neutral En desacuerdo Muy en desacuerdo