Interfaz de usuario

En este documento, se explica cómo seguir el estilo de Glass y cómo implementar prácticas recomendadas comunes de la IU que pueden optimizar la experiencia del usuario. Abarca los siguientes elementos de la IU:

Tema

El tema de Glass que sugerimos que utilices tiene las siguientes características:

  • Muestra las actividades en pantalla completa sin barra de acciones.
  • Aplica un fondo negro liso.
  • Establece el color más claro para el efecto de borde de color.
  • Aplica un color de texto blanco.

Las siguientes son las opciones de configuración de temas recomendadas para Glass:

 <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
   <item name="android:windowBackground">@android:color/black</item>
   <item name="android:colorEdgeEffect">@android:color/white</item>
   <item name="android:textColor">@android:color/white</item>
 </style>

Diseños XML

Estos son los dos diseños de tarjeta básicos que pueden ampliar tus fragmentos:

Diseño principal

Este diseño define el padding estándar y el pie de página sugeridos para una tarjeta. Coloca tus propias vistas en el FrameLayout vacío.

La caja central ocupa la mayor parte del interior de la pantalla en 560 por 240 píxeles, con una pequeña barra en la parte inferior que mide 560 por 40 píxeles.
          También hay cuatro bloques pequeños de 40 por 40 píxeles, uno en cada esquina.

Este es un ejemplo de diseño XML:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <FrameLayout
      android:id="@+id/body_layout"
      android:layout_width="0dp"
      android:layout_height="0dp"
      android:layout_margin="@dimen/glass_card_margin"
      app:layout_constraintBottom_toTopOf="@id/footer"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent">

    <!-- Put your widgets inside this FrameLayout. -->

  </FrameLayout>

  <!-- The footer view will grow to fit as much content as possible while the
         timestamp view keeps its width. If the footer text is too long, it
         will be ellipsized with a 40dp margin between it and the timestamp. -->

  <TextView
      android:id="@+id/footer"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginStart="@dimen/glass_card_margin"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toStartOf="@id/timestamp"
      app:layout_constraintStart_toStartOf="parent" />

  <TextView
      android:id="@+id/timestamp"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAlignment="viewEnd"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Diseño de la columna izquierda

Este diseño define una columna de ancho izquierdo de un tercio y una columna de ancho de dos tercios derecha en forma de dos clases FrameLayout en las que puedes colocar tus vistas. Consulta la siguiente imagen para ver un ejemplo.

Muestra una columna izquierda de 240 por 360 píxeles, que desplaza el diseño principal.
          Su tamaño se contrae para ajustarse; el área principal es de 330 por 240 píxeles, con una pequeña barra inferior de 330 x 40 píxeles. Las dos esquinas derechas tienen dos cuadros pequeños de 40 x 40 píxeles y cuatro cuadros de 30 x 40 píxeles, dos en las esquinas inferiores de la columna izquierda y dos en el lado izquierdo del diseño principal, uno en la parte superior y otro en la inferior.

Este es un ejemplo de diseño XML:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <FrameLayout
      android:id="@+id/left_column"
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:background="#303030"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintWidth_percent=".333">

    <!-- Put widgets for the left column inside this FrameLayout. -->

  </FrameLayout>

  <FrameLayout
      android:id="@+id/right_column"
      android:layout_width="0dp"
      android:layout_height="0dp"
      android:layout_marginTop="@dimen/glass_card_two_column_margin"
      android:layout_marginStart="@dimen/glass_card_two_column_margin"
      android:layout_marginBottom="@dimen/glass_card_two_column_margin"
      android:layout_marginEnd="@dimen/glass_card_margin"
      app:layout_constraintBottom_toTopOf="@id/footer"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toEndOf="@id/left_column"
      app:layout_constraintTop_toTopOf="parent">

    <!-- Put widgets for the right column inside this FrameLayout. -->

  </FrameLayout>

  <!-- The footer view will grow to fit as much content as possible while the
         timestamp view keeps its width. If the footer text is too long, it
         will be ellipsized with a 40dp margin between it and the timestamp. -->

  <TextView
      android:id="@+id/footer"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginStart="@dimen/glass_card_margin"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toStartOf="@id/timestamp"
      app:layout_constraintStart_toEndOf="@id/left_column" />

  <TextView
      android:id="@+id/timestamp"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAlignment="viewEnd"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Dimensiones estándar

Usa lo siguiente junto con los diseños anteriores o con tus propios diseños para crear un archivo que cumpla con el estilo estándar de Glass. Crea este archivo como res/values/dimens.xml en tu proyecto de Android.

<?xml version="1.0" encoding="utf-8"?>
<resources>

  <!-- The recommended margin for the top, left, and right edges of a card. -->
  <dimen name="glass_card_margin">40dp</dimen>

  <!-- The recommended margin between the bottom of the card and the footer. -->
  <dimen name="glass_card_footer_margin">50dp</dimen>

  <!-- The recommended margin for the left column of the two-column card. -->
  <dimen name="glass_card_two_column_margin">30dp</dimen>

</resources>

Te sugerimos que uses RecyclerView para compilar menús. Se deben basar en el archivo de menú estándar de Android de los recursos del proyecto de Android Studio. Android te permite anular la creación del menú estándar y reemplazarla con tu implementación. Para ello, haz lo siguiente:

  1. Crea el diseño con RecyclerView y establécelo como la vista de tu Activity.
  2. Configura RecyclerView y su adaptador para usar la colección recién creada de elementos del menú.
  3. Anula el método onCreateOptionsMenu.
    1. Aumenta tu menú y agrega el nuevo elemento a la colección para cada elemento del menú.
    2. Llama al método notifyDataSetChanged en el adaptador.

    Kotlin

        override fun onCreateOptionsMenu(menu: Menu): Boolean {
            val menuResource = intent
                .getIntExtra(EXTRA_MENU_KEY, EXTRA_MENU_ITEM_DEFAULT_VALUE)
            if (menuResource != EXTRA_MENU_ITEM_DEFAULT_VALUE) {
                menuInflater.inflate(menuResource, menu)
                for (i in 0 until menu.size()) {
                    val menuItem = menu.getItem(i)
                    menuItems.add(
                        GlassMenuItem(
                            menuItem.itemId, menuItem.icon,
                            menuItem.title.toString()
                        )
                    )
                    adapter.notifyDataSetChanged()
                }
            }
            return super.onCreateOptionsMenu(menu)
        }
        

    Java

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
          final int menuResource = getIntent()
              .getIntExtra(EXTRA_MENU_KEY, EXTRA_MENU_ITEM_DEFAULT_VALUE);
          if (menuResource != EXTRA_MENU_ITEM_DEFAULT_VALUE) {
            final MenuInflater inflater = getMenuInflater();
            inflater.inflate(menuResource, menu);
    
            for (int i = 0; i < menu.size(); i++) {
              final MenuItem menuItem = menu.getItem(i);
              menuItems.add(
                  new GlassMenuItem(menuItem.getItemId(), menuItem.getIcon(),
                      menuItem.getTitle().toString()));
              adapter.notifyDataSetChanged();
            }
          }
          return super.onCreateOptionsMenu(menu);
        }
        
  4. Usa OnScrollListener junto con LayoutManager y SnapHelper para determinar qué opción se seleccionó.
  5. Escucha un gesto de TAP para controlar el evento de selección del elemento de menú.
  6. Crea un Intent con información sobre el elemento de menú seleccionado.
  7. Establece un resultado para esta actividad y complétalo.
  8. Llama a startActivityForResult desde el fragmento o la actividad en los que quieras tener un menú. Para ello, usa un gesto de TAP.
  9. Anula onActivityResult en la actividad o el fragmento que realiza la llamada para controlar el elemento de menú seleccionado.

Lineamientos

La siguiente es una lista de sugerencias sobre cómo configurar el diseño del menú:

La siguiente imagen es un ejemplo de un diseño de menú personalizado:

Esta imagen sencilla muestra un fondo negro con las palabras &quot;Diseño MENÚ&quot; centrada en la pantalla y un símbolo de teléfono adyacente.

Revisa la app de muestra de tarjeta para ver los detalles de la implementación.

Páginas deslizables

La pantalla y el panel táctil de Glass funcionan en conjunto para mostrar tarjetas deslizables de una manera conveniente. Puedes crear páginas deslizables en tu actividad con la API estándar de ViewPager de Android.

Consulta la documentación de capacitación sobre la Diapositiva de pantalla para obtener más información sobre cómo usar Android ViewPager a fin de desplazarte por las tarjetas o las pantallas.