Interface do usuário

Este documento explica como seguir o estilo do Glass e implementar práticas recomendadas comuns de UI que podem otimizar a experiência do usuário. Ele abrange os seguintes elementos da interface:

Tema

O tema do Glass que sugerimos tem as seguintes características:

  • Mostra atividades em tela cheia sem barra de ações.
  • Aplica um plano de fundo preto sólido.
  • Define a cor mais clara para o efeito de borda de cor.
  • Aplica uma cor de texto branca.

Estas são as configurações de tema recomendadas para o 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>

Layouts XML

Confira os dois layouts de card básicos que seus fragmentos podem inflar:

Layout principal

Esse layout define o padding e o rodapé padrão sugeridos para um card. Coloque suas próprias visualizações no FrameLayout vazio.

A caixa central ocupa a maior parte do interior da tela com 560 x 240 pixels e uma pequena barra na parte de baixo com 560 x 40 pixels.
          Há também quatro pequenos blocos de 40 por 40 pixels, um em cada canto.

Confira um exemplo de layout 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>

Layout de coluna à esquerda

Esse layout define uma coluna esquerda com um terço da largura e uma coluna direita com dois terços da largura na forma de duas classes FrameLayout em que você pode colocar suas visualizações. Confira um exemplo na imagem a seguir.

Mostra uma coluna à esquerda com 240 por 360 pixels, que empurra o layout principal.
          O tamanho é ajustado para caber, a área principal tem 330 por 240 pixels, com uma pequena barra inferior de 330 por 40 pixels. Os dois cantos direitos têm duas pequenas caixas de 40 por 40 pixels, e há outras quatro caixas de 30 por 40 pixels, duas nos cantos inferiores da coluna esquerda e duas no lado esquerdo do layout principal, uma em cima e outra embaixo.

Confira um exemplo de layout 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>

Dimensões padrão

Use o seguinte em conjunto com os layouts anteriores ou seus próprios layouts para criar um arquivo que siga o estilo padrão do Glass. Crie esse arquivo como res/values/dimens.xml no seu projeto 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>

Sugerimos que você use RecyclerView para criar menus. Eles precisam ser baseados no arquivo de menu padrão do Android dos recursos do projeto do Android Studio. O Android permite substituir a criação padrão de menus e substituí-la pela sua implementação. Para isso, siga estas etapas:

  1. Crie o layout com RecyclerView e defina-o como a visualização do seu Activity.
  2. Defina RecyclerView e o adaptador dele para usar a coleção de itens de menu recém-criada.
  3. Substitua o método onCreateOptionsMenu.
    1. Inflacione o menu e adicione o novo elemento à coleção para cada item do menu.
    2. Chame o método notifyDataSetChanged no 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. Use OnScrollListener com LayoutManager e SnapHelper para determinar qual opção foi selecionada.
  5. Detecte um gesto de TAP para processar o evento de seleção do item de menu.
  6. Crie um Intent com informações sobre o item de menu selecionado.
  7. Defina um resultado para essa atividade e termine-a.
  8. Chame startActivityForResult do fragmento ou da atividade em que você quer ter um menu. Use um gesto de TAP para isso.
  9. Substitua o onActivityResult no fragmento ou atividade de chamada para processar o item de menu selecionado.

Diretrizes

Confira a seguir algumas sugestões de como configurar o layout do menu:

A imagem a seguir é um exemplo de layout de menu personalizado:

Esta imagem simples mostra um fundo preto com as palavras &quot;Layout do MENU&quot; centralizadas na tela e um símbolo de smartphone ao lado.

Confira o app de exemplo de cartão para detalhes da implementação.

Páginas deslizantes

A tela e o touchpad do Glass funcionam juntos para mostrar cards deslizáveis de maneira conveniente. Você pode criar páginas deslizáveis na sua atividade com a API padrão do Android ViewPager.

Acesse a documentação de treinamento Deslizar a tela para saber mais sobre como usar o ViewPager do Android para rolar cards ou telas.