MDC-104 Android: componentes avançados do Material Design (Java)

1. Introdução

logo_components_color_2x_web_96dp.png

Os componentes do Material Design (MDC, na sigla em inglês) ajudam os desenvolvedores a implementar o Material Design. Criados por uma equipe de engenheiros e designers de UX do Google, os MDC apresentam dezenas de componentes de interface bonitos e funcionais e estão disponíveis para Android, iOS, Web e Flutter.material.io/develop

No codelab MDC-103, você personalizou a cor, a elevação e a tipografia dos componentes do Material Design (MDC) para definir o estilo do app.

Um componente do sistema do Material Design realiza um conjunto de tarefas predefinidas e tem características específicas, como um botão. No entanto, um botão é mais do que apenas uma maneira de um usuário realizar uma ação. Ele também é uma expressão visual de forma, tamanho e cor que indica aos usuários que ele é interativo e que acontecerá algo quando os usuários clicarem ou tocarem nele.

As diretrizes do Material Design descrevem os componentes do ponto de vista de um designer. Elas descrevem uma grande variedade de funções básicas disponíveis nas plataformas, além dos elementos anatômicos que fazem parte de cada componente. Por exemplo, um pano de fundo contém uma camada de fundo e o conteúdo dela, uma camada em primeiro plano e o conteúdo dela, regras de movimento e opções de exibição. Cada um desses componentes pode ser personalizado conforme as necessidades, os casos de uso e o conteúdo de cada app. Essas partes são, na maioria, visualizações, controles e funções tradicionais do SDK da plataforma.

Embora as diretrizes do Material Design mencionem muitos componentes, nem todos são bons candidatos para serem reutilizados no código e, portanto, não podem ser encontrados nos MDC. Você pode criar essas experiências por conta própria para dar um estilo personalizado ao app. Tudo isso usando um código tradicional.

O que você vai criar

Neste codelab, você vai adicionar um pano de fundo ao Shrine. Os produtos mostrados na grade assimétrica por categoria serão filtrados. Você vai usar o seguinte:

  • Forma
  • Movimento
  • Classes tradicionais do SDK do Android

21c025467527a18e.png dcde66003cd51a5.png

Componentes MDC-Android neste codelab

  • Forma

O que é necessário

  • Conhecimento básico de desenvolvimento para Android.
  • Android Studio (faça o download dele aqui, caso ainda não tenha feito)
  • Um dispositivo ou emulador Android (disponível no Android Studio)
  • O exemplo de código (confira a próxima etapa)

Como você classificaria seu nível de experiência na criação de apps Android?

Iniciante Intermediário Proficiente

2. Configurar o ambiente de desenvolvimento

Está continuando do MDC-103?

Se você concluiu o MDC-103, o código para este codelab já está pronto. Vá para a etapa 3.

Está começando do zero?

Faça o download do app inicial do codelab

O app inicial está localizado no diretório material-components-android-codelabs-104-starter/java. Insira cd nesse diretório antes de começar.

... ou clone-o do GitHub

Para clonar este codelab do GitHub, execute estes comandos:

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

Carregar o código inicial no Android Studio

  1. Quando o assistente de configuração for concluído e a janela Welcome to Android Studio for exibida, clique em Open an existing Android Studio project. Navegue até o diretório em que você instalou o exemplo de código e selecione java -> santuário (ou pesquise por shrine no computador) para abrir o projeto do Shrine.
  2. Aguarde um pouco enquanto o Android Studio cria e sincroniza o projeto, conforme mostrado nos indicadores de atividade na parte inferior da janela.
  3. Como o SDK do Android ou as ferramentas de compilação não estão presentes, o Android Studio poderá encontrar alguns erros de compilação. Veja um exemplo a seguir. Siga as instruções no Android Studio para instalar/atualizar essas ferramentas e sincronizar o projeto.

F5H6srsw_5xOPGFpKrm1RwgewatxA_HUbDI1PWoQUAoJcT6DpfBOkAYwq3S-2vUHvweUaFgAmG7BtUKkGouUbhTwXQh53qec8tO5eVecdlo7QIoLc8rNxFEBb8l7RlS-KzBbZOzVhA

Adicionar dependências do projeto

O projeto precisa de uma dependência na Biblioteca de Suporte do Android para MDC. O exemplo de código que você baixou já deve ter essa dependência listada, mas é recomendável seguir as etapas a seguir para ter certeza.

  1. Navegue até o arquivo build.gradle do módulo app e verifique se o bloco dependencies inclui uma dependência no MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (Opcional) Se necessário, edite o arquivo build.gradle para adicionar as dependências a seguir e sincronizar o projeto.
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'
}

Executar o app inicial

  1. Confira se a configuração do build à esquerda do botão Run / Play é app.
  2. Pressione o botão verde Run / Play para criar e executar o app.
  3. Na janela Select Deployment Target, se você já tiver um dispositivo Android listado entre os dispositivos disponíveis, pule para a Etapa 8. Caso contrário, clique em Create New Virtual Device.
  4. Na tela Select Hardware, selecione um smartphone, como o Pixel 2, e clique em Next.
  5. Na tela System Image, selecione uma versão recente do Android, de preferência o nível da API mais alto. Se ele não estiver instalado, clique no link Download exibido e faça o download.
  6. Clique em Next.
  7. Na tela Android Virtual Device (AVD), deixe as configurações como estão e clique em Finish.
  8. Selecione um dispositivo Android na caixa de diálogo de destino da implantação.
  9. Clique em OK.
  10. O Android Studio cria o app, faz a implantação e o abre automaticamente no dispositivo de destino.

Pronto. Você verá o app Shrine em execução no dispositivo.

79eaeaff51de5719.png

3. Adicionar o menu do pano de fundo

Um pano de fundo é a superfície traseira de um app e aparece atrás de todos os outros conteúdos e componentes. Ele é composto por duas superfícies: uma camada de fundo, que exibe ações e filtros, e uma camada em primeiro plano, que exibe o conteúdo. Você pode usar um pano de fundo para exibir informações e ações interativas, como filtros de navegação ou conteúdo.

Ocultar o conteúdo da grade

Em shr_product_grid_fragment.xml, adicione o atributo android:visibility="gone" ao seu NestedScrollView para remover temporariamente o conteúdo do produto:

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 um pano de fundo nessa região. Para evitar a divisão entre a barra de apps superior e o conteúdo do menu que aparece no pano de fundo, usaremos a mesma cor da barra de apps superior.

Em shr_product_grid_fragment.xml, adicione o seguinte como o primeiro elemento na FrameLayout raiz, antes da 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>

Em styles.xml, inclua o seguinte:

styles.xml

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

Muito bem! Você adicionou um lindo pano de fundo à interface do Shrine. Em seguida, adicionaremos um menu.

Adicionar o menu

Um menu é essencialmente uma lista de botões de texto. Vamos adicionar uma aqui.

Crie um novo layout com o nome shr_backdrop.xml no diretório res -> layout e adicione o seguinte:

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>

E adicione esta lista ao LinearLayout que você acabou de incluir no arquivo shr_product_grid_fragment.xml usando uma tag <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>

Crie e execute. A tela inicial ficará assim:

a87a58e2ccddbae5.png

Seu pano de fundo está pronto. Vamos trazer de volta o conteúdo que escondemos anteriormente.

4. Adicionar uma forma

Antes de fazermos qualquer mudança no Shrine neste codelab, o conteúdo principal do produto estava localizado na superfície traseira mais distante. Ao adicionar um pano de fundo, esse conteúdo agora é mais enfatizado porque aparece na frente dele.

Adicionar uma nova camada

A camada da grade de produtos deve ser mostrada novamente. Remova o atributo android:visibility="gone" do seu 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">

Vamos estilizar a camada em primeiro plano com um entalhe no canto superior esquerdo. O Material Design se refere a esse tipo de personalização como uma forma. As superfícies do Material Design podem ser mostradas em diferentes formas. As formas dão ênfase e estilo às superfícies e podem ser usadas para expressar o branding. As formas do Material Design podem ter cantos e bordas curvos ou inclinados e qualquer número de lados. Elas podem ser simétricas ou irregulares.

Adicionar uma forma

Modifique a forma da grade. Fornecemos um plano de fundo de forma personalizada, mas o formato só é exibido corretamente no Android Marshmallow e versões mais recentes. Podemos definir o plano de fundo shr_product_grid_background_shape no NestedScrollView apenas para o Android Marshmallow e versões mais recentes. Primeiro, adicione um id ao NestedScrollView para que possamos referenciá-lo no código, da seguinte maneira:

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">

Em seguida, defina o plano de fundo de forma programática em ProductGridFragment.java. Adicione a seguinte lógica para definir o plano de fundo para o fim de onCreateView(), logo antes da instrução de retorno:

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 fim, atualizaremos o recurso de cor productGridBackgroundColor, também usado pelo plano de fundo da forma personalizada, da seguinte maneira:

colors.xml

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

Crie e execute:

9cf7a94091438011.png

Definimos uma forma personalizada para a superfície principal do Shrine. Devido à elevação da superfície, os usuários podem perceber que há algo por trás da camada branca. Vamos adicionar movimento para que os usuários possam ver o que há ali: o menu.

5. Adicionar movimento

Movimentos são uma forma de dar vida ao app. O movimento pode ser grande e dramático, sutil e mínimo, ou do jeito que você preferir. O tipo de movimento usado deve ser adequado à situação. Os movimentos aplicados a ações regulares repetidas devem ser pequenos e sutis, para que não tomem muito tempo regularmente. Outras situações, como a primeira vez que um usuário abre um app, podem ser mais chamativas e ajudar a educar o usuário sobre como usar o app.

Adicionar um movimento de revelação ao botão de menu

O movimento é a forma que está à frente e se move para baixo. Já fornecemos um listener de clique para você realizar a animação de tradução da planilha, em NavigationIconClickListener.java. Podemos definir esse listener de clique dentro do método setupToolbar() de ProductGridFragment.java:

ProductGridFragment.java

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

Seu método setUpToolbar() agora ficará assim:

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)));
}

Crie e execute. Pressione o botão de menu:

46a878bade66f821.png

Pressionar o ícone do menu de navegação novamente deve ocultar o menu.

Ajustar o movimento da camada em primeiro plano

Movimentos são uma ótima maneira de expressar sua marca. Vamos conferir como é a animação de revelação usando uma curva de tempo diferente.

Atualize o código em setupToolbar() em ProductGridFragment.java para transmitir um interpolador ao listener de clique do ícone de navegação, da seguinte maneira:

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()));
}

Isso cria um efeito diferente, não é?

6. Ícone da marca

A iconografia da marca também se aplica aos ícones conhecidos. Vamos personalizar o ícone de revelação e mesclá-lo ao nosso título para criar um visual exclusivo para a marca.

Mudar o ícone do botão de menu

Alterar o botão de menu para exibir um ícone com um desenho de losango. Atualize a barra de ferramentas no shr_product_grid_fragment.xml para usar o novo ícone de marca que fornecemos (shr_branded_menu) e defina os atributos app:contentInsetStart e android:padding para que a barra de ferramentas corresponda melhor às especificações do designer:

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" />

Atualize nosso listener de clique novamente em setupToolbar() em ProductGridFragment.java para usar drawables para a barra de ferramentas quando o menu estiver aberto e fechado, da seguinte maneira:

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
}

Crie e execute:

21c025467527a18e.png dcde66003cd51a5.png

Legal! Quando o pano de fundo puder ser revelado, o ícone do menu de diamante será exibido. Quando o menu pode ficar oculto, um ícone "Fechar" aparece.

7. Recapitulação

Nestes quatro codelabs, você viu como usar os componentes do Material Design para criar experiências do usuário únicas e elegantes que expressam a personalidade e o estilo de uma marca.

Próximas etapas

Este codelab, o MDC-104, encerra essa sequência de codelabs. Acesse o catálogo de widgets do Android para explorar ainda mais componentes no MDC-Android.

Como outro desafio neste codelab, modifique o aplicativo Shrine para mudar as imagens do produto exibidas quando uma categoria é selecionada no menu do pano de fundo.

Para saber como conectar esse app ao Firebase para ter um back-end funcional, consulte o Firebase Android Codelab.

Este codelab exigiu esforço e tempo normais para ser concluído

Concordo totalmente Concordo Não concordo nem discordo Discordo Discordo totalmente

Quero continuar usando componentes do Material Design no futuro

Concordo totalmente Concordo Neutro Discordo Discordo totalmente