MDC-101 Android: noções básicas dos componentes do Material Design (MDC) (Kotlin)

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 oferecem dezenas de componentes de IU bonitos e funcionais disponíveis para Android, iOS, Web e Flutter.

material.io/develop

O que são o Material Design e os componentes dele para Android?

O Material Design é um sistema para criar produtos digitais bonitos e arrojados. Ao combinar estilo, branding, interação e movimento em um conjunto consistente de princípios e componentes, as equipes de produto podem atingir o maior potencial de design.

Para apps Android, os Componentes do Material Design para Android(MDC Android) combinam design e engenharia com uma biblioteca de componentes para criar consistência no app. À medida que o sistema do Material Design evolui, esses componentes são atualizados para garantir uma implementação perfeita de pixels e a conformidade com os padrões de desenvolvimento de front-end do Google. Os MDC também estão disponíveis para Web, iOS e Flutter.

Neste codelab, você criará uma página de login usando vários componentes MDC para Android.

O que você vai criar

Este é o primeiro de quatro codelabs que ajudarão você a criar o app Shrine, um app Android de comércio eletrônico que vende roupas e artigos domésticos. Você verá como personalizar componentes para refletir qualquer marca ou estilo usando o MDC Android.

Neste codelab, você criará uma página de login para o Shrine que contém:

  • Dois campos de texto: um para inserir um nome de usuário e outro para uma senha.
  • Dois botões, um para "quot;Cancel" e outro para "próximo"
  • O nome do app (Shrine).
  • A imagem do logotipo do Shrine.

Componentes MDC do Android neste codelab

  • Campo de texto
  • Botão

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 (veja a próxima etapa)

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

Iniciante Intermediário Proficiente

Iniciar o Android Studio

Ao abrir o Android Studio, você verá uma janela com o título "Welcome to Android Studio". No entanto, se você estiver iniciando essa ferramenta pela primeira vez, siga as etapas do assistente de configuração do Android Studio com os valores padrão. O sistema pode demorar vários minutos para fazer o download e instalar os arquivos necessários, então você pode deixar o programa em execução em segundo plano enquanto acompanha a próxima seção.

Faça o download do app inicial do codelab

Faça o download do app inicial

O app inicial está localizado no diretório material-components-android-codelabs-101-starter/kotlin.

... 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 101-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 kotlin -> Shrine (ou pesquise shrine no seu computador para abrir o projeto de envio.
  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.

Adicionar dependências do projeto

O projeto precisa de uma dependência na Biblioteca de Suporte Android MDC. O exemplo de código transferido por download já precisa ter essa dependência listada, mas recomendamos seguir as etapas abaixo para garantir isso.

  1. Navegue até o arquivo build.gradle do módulo app e confira 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 seguintes dependências 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 nos seus 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 Próxima.
  7. Na tela Android Virtual Device (AVD), mantenha 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. O código inicial da página de login do Shrine será executado no emulador. Você verá o nome "Shrine" e o logotipo do Shrine abaixo dele.

Vamos dar uma olhada no código. Fornecemos um framework de navegação simples Fragment no exemplo de código para exibir fragmentos e navegar entre fragmentos.

Abra MainActivity.kt no diretório shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.kotlin.shrine. Ele conterá o código a seguir:

MainActivity.kt

package com.google.codelabs.mdc.kotlin.shrine

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

class MainActivity : AppCompatActivity(), NavigationHost {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.shr_main_activity)

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

   override fun navigateTo(fragment: Fragment, addToBackstack: Boolean) {
       val transaction = supportFragmentManager
               .beginTransaction()
               .replace(R.id.container, fragment)

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

       transaction.commit()
   }
}

Essa atividade exibe o arquivo de layout R.layout.shr_main_activity, definido em shr_main_activity.xml.

Observe que, no onCreate(),, o MainActivity.kt inicia uma transação Fragment para mostrar o LoginFragment. Neste codelab, modificaremos LoginFragment. A atividade também implementa um método navigateTo(Fragment), definido em NavigationHost, que permite que qualquer fragmento navegue até outro fragmento.

Command + clique (ou Control + clique) shr_main_activity no arquivo de atividade para abrir o arquivo de layout ou navegar até o arquivo de layout em 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"/>

Aqui, vemos uma <FrameLayout> simples, que funciona como um contêiner para qualquer fragmento exibido pela atividade.

Agora, vamos abrir o LoginFragment.kt.

LoginFragment.kt (link em inglês)

package com.google.codelabs.mdc.kotlin.shrine

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

class LoginFragment : Fragment() {

   override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment
       val view = inflater.inflate(R.layout.shr_login_fragment, container, false)

       return view
   }
}

LoginFragment infla o arquivo de layout shr_login_fragment e o exibe em onCreateView().

Agora, vamos ver o arquivo de layout shr_login_fragment.xml para ver a aparência da página de login.

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

Aqui, podemos ver uma <LinearLayout> com uma <ImageView> na parte superior, representando o logotipo do Shrine.

Depois disso, há uma tag <TextView> que representa o rótulo do Shrine abaixo do logotipo. O texto desse rótulo é um recurso de string chamado @string/shr_app_name. Se você pressionar Command + Click (ou Control + Click) ou abrir app -> res -> values -> strings.xml, poderá ver o arquivo strings.xml em que os recursos de string estão definidos. Quando forem adicionados mais recursos de string no futuro, eles serão definidos aqui. Cada recurso nesse arquivo precisa ter um prefixo shr_ para indicar que faz parte do app Shrine.

Agora que você já conhece o código inicial, vamos implementar nosso primeiro componente.

Para começar, adicione dois campos de texto à página de login para as pessoas digitarem o nome de usuário e a senha. Usaremos o componente Campo de texto do MDC, que inclui a funcionalidade integrada que exibe um marcador flutuante e mensagens de erro.

Adicionar o XML

Em shr_login_fragment.xml, adicione dois elementos TextInputLayout com um TextInputEditText filho dentro do <LinearLayout>, abaixo do rótulo "SHRINE" <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" />
</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>

O snippet acima representa dois campos de texto, cada um composto por um elemento <TextInputLayout> e um filho <TextInputEditText>. O texto de dica de cada campo é especificado no atributo android:hint.

Incluímos dois novos recursos de string para o campo de texto: @string/shr_hint_username e @string/shr_hint_password. Abra strings.xml para ver esses recursos de string.

strings.xml

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

Adicionar validação de entrada

Os componentes do TextInputLayout têm a funcionalidade integrada de feedback de erro.

Para mostrar o feedback de erro, faça as seguintes mudanças em shr_login_fragment.xml:

  • Defina o atributo app:errorEnabled como true no elemento PasswordTextInputLayout. Isso adicionará um padding extra à mensagem de erro abaixo do campo de texto.
  • Defina o atributo android:inputType como "textPassword" no elemento SenhaTextInputEditText. Isso ocultará o texto de entrada no campo da senha.

Com essas mudanças, os campos de texto em shr_login_fragment.xml ficarão assim:

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

Agora, execute o app. Você verá uma página com dois campos de texto sobre "nome de usuário" e "senha".

Veja a animação de etiquetas flutuantes:

Em seguida, adicionaremos dois botões à página de login: "Cancel" e "Next". Usaremos o componente Botão do MDC, que vem com o icônico efeito de ondulação com tinta do Material Design.

Adicionar o XML

Em shr_login_fragment.xml, adicione um <RelativeLayout> à <LinearLayout>, abaixo dos elementos TextInputLayout. Em seguida, adicione dois elementos <MaterialButton> ao <RelativeLayout>.

O arquivo XML resultante terá esta aparência:

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>

Pronto! Quando você executar o app, uma ondulação será exibida quando você tocar em cada botão.

Por fim, adicionaremos um código Kotlin a LoginFragment.kt para conectar nosso botão "NEXT" para fazer a transição para outro fragmento.

Vamos adicionar um método booleano booleano isPasswordValid em LoginFragment.kt abaixo de onCreateView(), com lógica para determinar se a senha é válida ou não. Para esta demonstração, só vamos garantir que a senha tenha pelo menos 8 caracteres:

LoginFragment.kt (link em inglês)

private fun isPasswordValid(text: Editable?): Boolean {
   return text != null && text.length >= 8
}

Em seguida, adicione um listener de clique ao botão "quoquo;Next" que define e limpa o erro com base no método isPasswordValid() que acabamos de criar. Em onCreateView(), esse listener de clique precisa ser colocado entre a linha infladora e a linha return view.

Agora, vamos adicionar um listener de chave à senha TextInputEditText para detectar eventos de chave que limpariam o erro. Esse listener também precisa usar isPasswordValid() para verificar se a senha é válida ou não. Você pode adicionar isso diretamente abaixo do listener de clique em onCreateView().

O método onCreateView() será semelhante a este:

LoginFragment.kt (link em inglês)

override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment.
       val view = inflater.inflate(R.layout.shr_login_fragment, container, false)

       // Set an error if the password is less than 8 characters.
       view.next_button.setOnClickListener({
           if (!isPasswordValid(password_edit_text.text!!)) {
               password_text_input.error = getString(R.string.shr_error_password)
           } else {
               // Clear the error.
               password_text_input.error = null
           }
       })

       // Clear the error once more than 8 characters are typed.
       view.password_edit_text.setOnKeyListener({ _, _, _ ->
           if (isPasswordValid(password_edit_text.text!!)) {
               // Clear the error.
               password_text_input.error = null
           }
           false
       })

       return view
   }
}

Agora, podemos navegar para outro fragmento. No onCreateView(), atualize a OnClickListener para navegar até outro fragmento quando a validação do erro for concluída. Seu código clickListener ficará assim:

LoginFragment.kt (link em inglês)

// Set an error if the password is less than 8 characters.
view.next_button.setOnClickListener({
   if (!isPasswordValid(password_edit_text.text!!)) {
       password_text_input.error = getString(R.string.shr_error_password)
   } else {
       // Clear the error.
       password_text_input.error = null
       // Navigate to the next Fragment.
       (activity as NavigationHost).navigateTo(ProductGridFragment(), false)
   }
})

Adicionamos a linha (activity as NavigationHost).navigateTo(ProductGridFragment(), false) ao caso else do listener de clique. Essa linha chama o método navigateTo() da MainActivity para navegar até um novo fragmento: ProductGridFragment. No momento, esta é uma página vazia em que você trabalhará no MDC-102.

Agora, crie o app. Pressione o botão "Next".

Parabéns! Essa tela será o ponto de partida do nosso próximo codelab, em que você trabalhará no MDC-102.

Usando a marcação XML básica e cerca de 30 linhas de Kotlin, a biblioteca Material Components para Android ajudou você a criar uma bela página de login em conformidade com as diretrizes do Material Design e com aparência e comportamento consistentes em todos os dispositivos.

Próximas etapas

O campo de texto e o botão são dois componentes principais da biblioteca Android do MDC, mas há muito mais. Você pode explorar o restante dos componentes no MDC para Android. Como alternativa, consulte MDC 102: estrutura e layout do Material Design para saber mais sobre a barra superior de apps, a visualização de cards e o layout de grade. Agradecemos por testar os componentes do Material Design. Esperamos que tenha gostado deste 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 Não concordo nem discordo Discordo Discordo totalmente