Este codelab faz parte do curso Conceitos básicos do Kotlin para Android. Você vai aproveitar mais este curso se fizer os codelabs em sequência. Todos os codelabs do curso estão listados na página inicial dos codelabs de princípios básicos do Kotlin para Android.
Introdução
Fazer um app que possa ser usado pelo maior número possível de pessoas faz sentido, seja para se divertir ou para fins comerciais. Há várias dimensões para isso.
- Suporte a idiomas da direita para a esquerda (RTL, na sigla em inglês). O português e muitos outros idiomas são lidos da esquerda para a direita, e os apps originários dessas localidades são geralmente projetados para se adequar bem a esses idiomas. Muitos outros idiomas com um grande número de falantes são lidos da direita para a esquerda, como o árabe. Faça seu app funcionar com idiomas da direita para a esquerda (RTL) para aumentar seu público-alvo em potencial.
- Verificar a acessibilidade. Adivinhar como outra pessoa pode usar seu app é uma opção com armadilhas. O app Scanner de acessibilidade elimina as suposições e analisa seu app, identificando onde você pode melhorar a acessibilidade.
- Crie para o TalkBack com descrições de conteúdo. Deficiências visuais são mais comuns do que se imagina, e muitos usuários, não apenas cegos, usam um leitor de tela. As descrições de conteúdo são frases que um leitor de tela diz quando um usuário interage com um elemento da tela.
- Compatibilidade com o modo noturno. Para muitos usuários com deficiência visual, mudar as cores da tela melhora o contraste e ajuda a trabalhar visualmente com seu app. O Android facilita o suporte ao modo noturno, que deve ser sempre oferecido para dar aos usuários uma alternativa simples às cores padrão da tela.
Neste codelab, você vai explorar cada uma dessas opções e adicionar suporte a elas no app GDG Finder.
Você também vai aprender a usar chips com seu app Android para torná-lo mais interessante e acessível.
O que você já precisa saber
Você precisa:
- Como criar apps com atividades e fragmentos e navegar entre eles transmitindo dados.
- Usar visualizações e grupos de visualizações para criar uma interface do usuário, em especial, RecyclerView.
- Como usar os Componentes da arquitetura, incluindo
ViewModel
, com a arquitetura recomendada para criar um app bem estruturado e eficiente. - Vinculação de dados, corrotinas e como processar cliques do mouse.
- Como se conectar à Internet e armazenar dados em cache localmente usando um banco de dados Room.
- Como definir propriedades de visualização e extrair e usar recursos de arquivos de recursos XML.
- Como usar estilos e temas para personalizar a aparência do app.
- Como usar componentes do Material, recursos de dimensão e cores personalizadas.
O que você vai aprender
- Como permitir que o app seja usado pelo maior número de pessoas possível.
- Como fazer seu app funcionar em idiomas da direita para a esquerda (RTL).
- Como avaliar a acessibilidade do seu app.
- Como usar descrições de conteúdo para melhorar o funcionamento do app com leitores de tela.
- Como usar ícones.
- Como fazer seu app funcionar com o modo escuro.
Atividades deste laboratório
- Avalie e estenda um app para melhorar a acessibilidade, fazendo com que ele funcione para idiomas RTL.
- Analise o app para determinar onde a acessibilidade pode ser melhorada.
- Use descrições de conteúdo para imagens.
- Saiba como usar elementos gráficos.
- Adicione a capacidade de usar o modo noturno ao seu app.
O app inicial do GDG-finder se baseia em tudo o que você aprendeu até agora neste curso.
O app usa ConstraintLayout
para criar três telas. Duas das telas são apenas arquivos de layout que você vai usar para explorar cores e texto no Android.
A terceira tela é um localizador de GDG. Os GDGs, ou Google Developer Groups, são comunidades de desenvolvedores que se concentram em tecnologias do Google, incluindo o Android. Os GDGs do mundo todo organizam encontros, conferências, study jams e outros eventos.
Ao desenvolver esse app, você trabalha na lista real de GDGs. A tela do localizador usa a localização do dispositivo para classificar os GDGs por distância.
Se você tiver sorte e houver um GDG na sua região, confira o site e inscreva-se nos eventos deles. Os eventos do GDG são uma ótima maneira de conhecer outros desenvolvedores Android e aprender as práticas recomendadas do setor que não se encaixam neste curso.
As capturas de tela abaixo mostram como o app vai mudar do início ao fim deste codelab.
A principal diferença entre os idiomas da esquerda para a direita (LTR) e da direita para a esquerda (RTL) é a direção do conteúdo exibido. Quando a direção da interface é alterada de LTR para RTL (ou vice-versa), isso geralmente é chamado de espelhamento. O espelhamento afeta a maior parte da tela, incluindo texto, ícones de campo de texto, layouts e ícones com direções (como setas). Outros itens não são espelhados, como números (relógio, números de telefone), ícones sem direção (modo avião, Wi-Fi), controles de reprodução e a maioria dos gráficos.
Idiomas que usam a direção de texto RTL são falados por mais de um bilhão de pessoas no mundo todo. Os desenvolvedores Android estão em todo o mundo, então um app GDG Finder precisa oferecer suporte a idiomas RTL.
Etapa 1: adicionar compatibilidade com RTL
Nesta etapa, você vai fazer o app GDG Finder funcionar com idiomas RTL.
- Faça o download e execute o app GDGFinderMaterial, que é o app inicial deste codelab, ou continue com o código final do codelab anterior.
- Abra o manifesto do Android.
- Na seção
<application>
, adicione o código a seguir para especificar que o app é compatível com RTL.
<application
...
android:supportsRtl="true">
- Abra activity_main.xml na guia Design.
- No menu suspenso Localidade para visualização, escolha Visualizar da direita para a esquerda. Se você não encontrar esse menu, amplie o painel ou feche o painel Atributos para encontrá-lo.
- Na Prévia, observe que o cabeçalho "GDG Finder" foi movido para a direita, e o restante da tela permanece praticamente o mesmo. No geral, essa tela é aceitável. Mas o alinhamento na visualização de texto agora está errado, porque está alinhado à esquerda, em vez de à direita.
- Para que isso funcione no seu dispositivo, nas Configurações do dispositivo ou emulador, em Opções do desenvolvedor, selecione Forçar layout da direita p/ esquerda. Se você precisar ativar as Opções do desenvolvedor, encontre o Número da versão e clique nele até receber uma mensagem indicando que você é um desenvolvedor. Isso varia de acordo com o dispositivo e a versão do sistema Android.)
- Execute o app e verifique no dispositivo se a tela principal aparece igual à Prévia. O botão de ação flutuante agora está à esquerda, e o menu hambúrguer, à direita.
- No app, abra a gaveta de navegação e acesse a tela Pesquisar. Como mostrado abaixo, os ícones ainda estão à esquerda, e nenhum texto está visível. O texto está fora da tela, à esquerda do ícone. Isso acontece porque o código usa referências de tela esquerda/direita nas propriedades de visualização e restrições de layout.
Etapa 2: use "start" e "end" em vez de "left" e "right"
"Esquerda" e "direita" na tela (quando você está de frente para ela) não mudam, mesmo que a direção do texto mude. Por exemplo, layout_constraintLeft_toLeftOf
sempre restringe o lado esquerdo do elemento ao lado esquerdo da tela. No caso do seu app, o texto fica fora da tela em idiomas RTL, como mostrado na captura de tela acima.
Para corrigir isso, em vez de "esquerda" e "direita", use a terminologia Start
e End
. Essa terminologia define o início e o fim do texto de acordo com a direção do texto no idioma atual, para que as margens e os layouts estejam nas áreas corretas das telas.
Open
list_item.xml.- Substitua as referências a
Left
eRight
por referências aStart
eEnd
.
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintStart_toEndOf="@+id/gdg_image"
app:layout_constraintEnd_toEndOf="parent"
- Substitua o
layout_marginLeft
doImageView
porlayout_marginStart
. Isso move a margem para o lugar correto e afasta o ícone da borda da tela.
<ImageView
android:layout_marginStart="
?
- Abra
fragment_gdg_list.xml
. Confira a lista de GDGs no painel Visualização. O ícone ainda está apontando na direção errada porque está espelhado. Se ele não estiver espelhado, confira se você ainda está visualizando a prévia da direita para a esquerda. De acordo com as diretrizes do Material Design, os ícones não devem ser espelhados. - Abra res/drawable/ic_gdg.xml.
- Na primeira linha do código XML, encontre e exclua
android:autoMirrored="true"
para desativar o espelhamento. - Verifique a Prévia ou execute o app novamente e abra a tela "Pesquisar GDG". O layout deve estar corrigido agora.
Etapa 3: deixe o Android Studio fazer o trabalho por você
No exercício anterior, você deu os primeiros passos para oferecer suporte a idiomas RTL. Felizmente, o Android Studio pode analisar seu app e configurar muitos elementos básicos para você.
- Em list_item.xml, no
TextView
, mudelayout_marginStart
de volta paralayout_marginLeft
para que o scanner tenha algo para encontrar.
<TextView
android:layout_marginLeft="@dimen/spacing_normal"
- No Android Studio, escolha Refactor > Add RTL support where possible e marque as caixas para atualizar o manifesto e os arquivos de layout para usar as propriedades de início e fim.
- No painel Refactoring Preview, encontre a pasta app e expanda até que todos os detalhes estejam abertos.
- Na pasta do app, observe que o
layout_marginLeft
que você acabou de mudar está listado como código a ser refatorado.
- A visualização também lista arquivos de sistema e de biblioteca. Clique com o botão direito do mouse em layout e layout-watch-v20 e em qualquer outra pasta que não faça parte de app. Em seguida, escolha Excluir no menu de contexto.
- Faça a refatoração agora. Se aparecer um pop-up sobre arquivos do sistema, verifique se você excluiu todas as pastas que não fazem parte do código do app.
- Observe que
layout_marginLeft
foi alterado de volta paralayout_marginStart
.
Etapa 3: explorar pastas de locais
Até agora, você apenas mudou a direção do idioma padrão usado no app. Para um app de produção, envie o arquivo strings.xml para um tradutor e peça que ele seja traduzido para um novo idioma. Para este codelab, o app fornece um arquivo strings.xml em espanhol. Usamos o Google Tradutor para gerar as traduções, então elas não são perfeitas.
- No Android Studio, mude a visualização do projeto para Arquivos do projeto.
- Abra a pasta res e observe as pastas res/values e res/values-es. O "es" no nome da pasta é o código do idioma para espanhol. As pastas values-"código de idioma" contêm valores para cada idioma compatível. A pasta values sem uma extensão contém os recursos padrão que se aplicam de outra forma.
- Em values-es, abra strings.xml e observe que todas as strings estão em espanhol.
- No Android Studio, abra
activity_main.xml
na guia Design. - No menu suspenso Localidade para visualização, escolha Espanhol. Seu texto agora vai estar em espanhol.
- [Opcional] Se você tiver proficiência em um idioma RTL, crie uma pasta values e um arquivo strings.xml nesse idioma e teste como ele aparece no seu dispositivo.
- [Opcional] Mude as configurações de idioma no seu dispositivo e execute o app. Não mude o dispositivo para um idioma que você não lê, porque isso dificulta o processo de desfazer a ação.
Na tarefa anterior, você mudou o app manualmente e usou o Android Studio para verificar se havia mais melhorias a serem feitas no RTL.
O app Scanner de acessibilidade é seu melhor aliado para tornar seu app acessível. Ele verifica o app no dispositivo de destino e sugere melhorias, como aumentar as áreas de toque, aumentar o contraste e fornecer descrições para imagens, tornando o app mais acessível. O Scanner de acessibilidade é um produto do Google e pode ser instalado na Play Store.
Etapa 1: instalar e executar o Scanner de acessibilidade
- Abra a Play Store e faça login se necessário. Você pode fazer isso no dispositivo físico ou no emulador. Este codelab usa o emulador.
- Na Play Store, pesquise Scanner de acessibilidade do Google LLC. Verifique se você baixou o app correto, emitido pelo Google, já que qualquer verificação requer muitas permissões.
- Instale o scanner no emulador.
- Depois da instalação, clique em Abrir.
- Clique em Primeiros passos.
- Clique em OK para iniciar a configuração do Scanner de acessibilidade em "Configurações".
- Clique no Scanner de acessibilidade para acessar as configurações de Acessibilidade do dispositivo.
- Clique em Usar serviço para ativar.
- Siga as instruções na tela e conceda todas as permissões.
- Em seguida, clique em OK, entendi e volte para a tela inicial. Talvez um botão azul com uma marca de seleção apareça em algum lugar da tela. Ao clicar nesse botão, o teste do app em primeiro plano é acionado. Para mudar a posição do botão, arraste-o. Esse botão fica na frente de todos os apps, para que você possa iniciar os testes a qualquer momento.
- Abra ou execute o app.
- Clique no botão azul e aceite outros avisos e permissões de segurança.
Na primeira vez que você clicar no ícone do Accessibility Scanner, o app vai pedir permissão para acessar tudo o que é mostrado na tela. Essa permissão parece muito assustadora, e é.
Você quase nunca deve conceder uma permissão como essa, porque ela permite que os apps leiam seu e-mail ou até mesmo acessem as informações da sua conta bancária. No entanto, para que o Scanner de acessibilidade funcione, ele precisa examinar seu app da mesma forma que um usuário faria. Por isso, ele precisa dessa permissão.
- Clique no botão azul e aguarde a conclusão da análise. Você vai ver algo como a captura de tela abaixo, com o título e o FAB em vermelho. Isso indica duas sugestões de melhorias de acessibilidade nessa tela.
- Clique na caixa ao redor do GDG Finder. Isso abre um painel com mais informações, como mostrado abaixo, indicando problemas com o contraste da imagem.
- Expanda as informações de Contraste da imagem. A ferramenta vai sugerir soluções.
- Clique nas setas à direita para acessar informações sobre o próximo item.
- No seu app, navegue até a tela Inscrever-se no GDG e faça a verificação com o app Scanner de acessibilidade. Isso vai gerar algumas sugestões, como mostrado abaixo à esquerda. 12, para ser exato. Para ser justo, alguns deles são duplicados de itens semelhantes.
- Clique no ícone de "pilha"
na barra de ferramentas da parte de baixo para conferir uma lista de todas as sugestões, conforme mostrado na captura de tela à direita. Você vai resolver todos esses problemas neste codelab.
O Pacote de Acessibilidade do Android, uma coleção de apps do Google, inclui ferramentas para ajudar a tornar os apps mais acessíveis. Ele inclui ferramentas como o TalkBack. O TalkBack é um leitor de tela que oferece feedback auditivo, tátil e falado, permitindo que os usuários naveguem e consumam conteúdo nos dispositivos sem usar os olhos.
O TalkBack não é usado apenas por pessoas cegas, mas também por muitas pessoas com deficiência visual de algum tipo. Ou até mesmo pessoas que só querem descansar os olhos!
Portanto, a acessibilidade é para todos! Nesta tarefa, você vai testar o TalkBack e atualizar o app para que ele funcione bem com o leitor de tela.
Etapa 1: instalar e executar a Acessibilidade do Android
O TalkBack vem pré-instalado em muitos dispositivos físicos, mas em um emulador, é necessário instalá-lo.
- Abra a Play Store.
- Encontre a Acessibilidade do Android. Confira se é o app correto do Google.
- Se ele não estiver instalado, instale o pacote Acessibilidade.
- Para ativar o TalkBack no dispositivo, acesse Configurações > Acessibilidade e ative o TalkBack selecionando Usar serviço. Assim como o verificador de acessibilidade, o TalkBack exige permissões para ler o conteúdo na tela. Depois que você aceitar as solicitações de permissão, o TalkBack vai mostrar uma lista de tutoriais para ensinar a usar o recurso de maneira eficaz.
- Faça uma pausa aqui e siga os tutoriais, mesmo que seja apenas para aprender a desativar o TalkBack quando terminar.
- Para sair do tutorial, clique no botão "Voltar" para selecionar e toque duas vezes em qualquer lugar da tela.
- Navegue usando o app GDG Finder com o TalkBack. Observe os lugares em que o TalkBack não oferece informações úteis sobre a tela ou um controle. Isso será corrigido no próximo exercício.
Etapa 2: adicionar uma descrição do conteúdo
Os descritores de conteúdo são rótulos descritivos que explicam o significado das visualizações. A maioria das suas visualizações precisa ter descrições de conteúdo.
- Com o app GDG Finder em execução e o TalkBack ativado, navegue até a tela Inscrever-se para executar o GDG.
- Toque na imagem principal ... e nada acontece.
- Abra add_gdg_fragment.xml.
- No
ImageView
, adicione um atributo de descritor de conteúdo, conforme mostrado abaixo. A stringstage_image_description
é fornecida em strings.xml.
android:contentDescription="@string/stage_image_description"
- Execute o app.
- Acesse Inscrever-se para administrar um GDG e clique na imagem. Você vai ouvir uma breve descrição da imagem.
- [Opcional] Adicione descrições de conteúdo para as outras imagens no app. Em um app de produção, todas as imagens precisam ter descrições de conteúdo.
Etapa 3: adicionar dicas aos campos de texto editáveis
Para elementos editáveis, como um EditText
, use android:hint
no XML para ajudar os usuários a descobrir o que digitar. Uma dica sempre aparece na interface, já que é o texto padrão em um campo de entrada.
- Ainda em add_gdg_fragment.xml.
- Adicione descrições e dicas de conteúdo usando o código abaixo como orientação.
Adicione ao textViewIntro
:
android:contentDescription="@string/add_gdg"
Adicione aos textos de edição, respectivamente:
android:hint="@string/your_name_label"
android:hint="@string/email_label"
android:hint="@string/city_label"
android:hint="@string/country_label"
android:hint="@string/region_label"
- Adicione uma descrição de conteúdo a
labelTextWhy
.
android:contentDescription="@string/motivation"
- Adicione uma dica a
EditTextWhy
. Depois de rotular as caixas de edição, adicione uma descrição de conteúdo ao rótulo e uma dica à caixa.
android:hint="@string/enter_motivation"
- Adicione uma descrição de conteúdo para o botão "Enviar". Todos os botões precisam ter uma descrição do que acontece se forem pressionados.
android:contentDescription="@string/submit_button_description"
- Execute o app com o TalkBack ativado e preencha o formulário para se inscrever e organizar um GDG.
Etapa 4: criar um grupo de conteúdo
Para controles de interface que o TalkBack precisa tratar como um grupo, use o agrupamento de conteúdo. O conteúdo relacionado que é agrupado é anunciado junto. Assim, os usuários de tecnologia assistiva não precisam deslizar, verificar ou esperar com tanta frequência para descobrir todas as informações na tela. Isso não afeta a aparência dos controles na tela.
Para agrupar componentes da interface, coloque-os em um ViewGroup
, como um LinearLayout
. No app GDG Finder, os elementos labelTextWhy
e editTextWhy
são excelentes candidatos para agrupamento, já que pertencem ao mesmo contexto semântico.
- Abra add_gdg_fragment.xml.
- Inclua um
LinearLayout
emLabelTextWhy
eEditTextWhy
para criar um grupo de conteúdo. Copie e cole o código abaixo. EsseLinearLayout
já contém parte do estilo necessário. Verifique se obutton
está FORA doLinearLayout
.
<LinearLayout android:id="@+id/contentGroup" android:layout_width="match_parent"
android:layout_height="wrap_content" android:focusable="true"
app:layout_constraintTop_toBottomOf="@id/EditTextRegion"
android:orientation="vertical" app:layout_constraintStart_toStartOf="@+id/EditTextRegion"
app:layout_constraintEnd_toEndOf="@+id/EditTextRegion"
android:layout_marginTop="16dp" app:layout_constraintBottom_toTopOf="@+id/button"
android:layout_marginBottom="8dp">
<!-- label and edit text here –>
<LinearLayout/>
- Escolha Code > Reformat code para aplicar o recuo correto a todo o código.
- Remova todas as margens de layout de
labelTextWhy
eeditTextWhy
. - Em
labelTextWhy
, mude a restriçãolayout_constraintTop_toTopOf
paracontentGroup
.
app:layout_constraintTop_toTopOf="@+id/contentGroup" />
- Em
editTextWhy
, mude a restriçãolayout_constraintBottom_toBottomOf
paracontentGroup
.
app:layout_constraintBottom_toBottomOf="@+id/contentGroup"
- Restrinja
EditTextRegion
e oButton
aocontentGroup
para se livrar dos erros.
app:layout_constraintBottom_toTopOf="@+id/contentGroup"
- Adicione margens à
LinearLayout
. Se quiser, extraia essa margem como uma dimensão.
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
Se precisar de ajuda, compare seu código com o add_gdg_fragment.xml
no código da solução.
- Execute o app e navegue pela tela Inscrever-se para executar o GDG com o TalkBack.
Etapa 5: adicionar uma região dinâmica
No momento, o rótulo do botão "Enviar" é OK. Seria melhor se o botão tivesse um rótulo e uma descrição antes do envio do formulário e mudasse dinamicamente para um rótulo e uma descrição de conteúdo diferentes depois que o usuário clicasse e o formulário fosse enviado. Para isso, use uma região dinâmica.
Uma região ativa indica aos serviços de acessibilidade se o usuário precisa ser notificado quando uma visualização muda. Por exemplo, informar o usuário sobre uma senha incorreta ou um erro de rede é uma ótima maneira de tornar seu app mais acessível. Neste exemplo, para simplificar, você informa ao usuário quando o botão de envio muda de estado.
- Abra add_gdg_fragment.xml.
- Mude a atribuição de texto do botão para Enviar usando o recurso de string
submit
fornecido.
android:text="@string/submit"
- Adicione uma região dinâmica ao botão definindo o atributo
android:accessibilityLiveRegion
. Ao digitar, você tem várias opções para o valor. Dependendo da importância da mudança, você pode escolher se quer interromper o usuário. Com o valor "assertive", os serviços de acessibilidade interrompem a fala em andamento para anunciar imediatamente as mudanças nessa visualização. Se você definir o valor como "none", nenhuma mudança será anunciada. Definido como "educado", os serviços de acessibilidade anunciam as mudanças, mas aguardam a vez. Defina o valor como "polite".
android:accessibilityLiveRegion="polite"
- No pacote add, abra AddGdgFragment.kt.
- Dentro do
showSnackBarEvent
Observer
, depois de mostrar oSnackBar
, defina uma nova descrição de conteúdo e texto para o botão.
binding.button.contentDescription=getString(R.string.submitted)
binding.button.text=getString(R.string.done)
- Execute o app e clique no botão. Infelizmente, o botão e a fonte estão muito pequenos.
Etapa 6: corrigir o estilo do botão
- Em add_gdg_fragment.xml, mude o
width
e oheight
do botão parawrap_content
. Assim, o rótulo completo fica visível e o botão tem um tamanho adequado.
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- Exclua os atributos
backgroundTint
,textColor
etextSize
do botão para que o app use o melhor estilo de tema. - Exclua o atributo
textColor
detextViewIntro
. As cores do tema precisam ter um bom contraste. - Execute o app. Observe que o botão Submit está muito mais utilizável. Clique em Enviar e observe como ele muda para Concluído.
Os ícones são elementos compactos que representam um atributo, texto, entidade ou ação. Com eles, os usuários podem inserir informações, selecionar uma opção, filtrar conteúdo ou acionar uma ação.
O widget Chip
é um wrapper de visualização fina em torno do ChipDrawable
, que contém toda a lógica de layout e desenho. A lógica extra existe para oferecer suporte à navegação por toque, mouse, teclado e acessibilidade. O ícone principal e o ícone de fechar são considerados subvisualizações lógicas separadas e contêm o próprio comportamento e estado de navegação.
Os ícones usam elementos gráficos. Os elementos gráficos do Android permitem desenhar imagens, formas e animações na tela, e podem ter um tamanho fixo ou dinâmico. Você pode usar imagens como drawables, como as imagens no app do GDG, e desenhos vetoriais para desenhar o que quiser. Há também um elemento de imagem redimensionável chamado elemento de imagem de nove patches, que não é abordado neste codelab. O logotipo do GDG, em drawable/ic_gdg.xml, é outro drawable.
Drawables não são visualizações. Portanto, não é possível colocar um drawable diretamente em um ConstraintLayout
. É necessário colocá-lo em um ImageView
. Você também pode usar elementos gráficos para fornecer um plano de fundo para uma visualização de texto ou um botão. O plano de fundo é desenhado atrás do texto.
Etapa 1: adicionar chips à lista de GDGs
O ícone de chip marcado abaixo usa três elementos gráficos. O plano de fundo e a marca de seleção são elementos gráficos. Ao tocar no ícone, um efeito de ondulação é criado com um RippleDrawable especial que mostra um efeito de ondulação em resposta a mudanças de estado.
Nesta tarefa, você vai adicionar chips à lista de GDGs e fazer com que eles mudem de estado quando forem selecionados. Neste exercício, você vai adicionar uma linha de botões chamada chips à parte de cima da tela Pesquisar. Cada botão filtra a lista do GDG para que o usuário receba apenas resultados da região selecionada. Quando um botão é selecionado, o plano de fundo dele muda e uma marca de seleção aparece.
- Abra fragment_gdg_list.xml.
- Crie um
com.google.android.material.chip.ChipGroup
dentro doHorizontalScrollView.
. Defina a propriedadesingleLine
comotrue
para que todos os chips fiquem alinhados em uma linha rolável horizontalmente. Defina a propriedadesingleSelection
comotrue
para que apenas um ícone no grupo possa ser selecionado por vez. Veja o código:
<com.google.android.material.chip.ChipGroup
android:id="@+id/region_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleSelection="true"
android:padding="@dimen/spacing_normal"/>
- Na pasta layout, crie um arquivo de recurso de layout chamado region.xml para definir o layout de uma
Chip
. - Em region.xml, substitua todo o código pelo layout de um
Chip
, conforme mostrado abaixo. Observe que esseChip
é um componente do Material. Observe também que você recebe a marca de seleção ao definir a propriedadeapp:checkedIconVisible
. Você vai receber um erro para a corselected_highlight
ausente.
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.chip.Chip
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.Chip.Choice"
app:chipBackgroundColor="@color/selected_highlight"
app:checkedIconVisible="true"
tools:checked="true"/>
- Para criar a cor
selected_highlight
ausente, coloque o cursor emselected_highlight
, abra o menu de intenção e crie um recurso de cor para o destaque selecionado. As opções padrão estão corretas, então basta clicar em OK. O arquivo é criado na pasta res/color. - Abra res/color/selected_highlight.xml. Nessa lista de estados de cores, codificada como um
<selector>
, você pode fornecer cores diferentes para estados diferentes. Cada estado e cor associada são codificados como um<item>
. Consulte Temas de cores para mais informações sobre essas cores.
- Dentro do
<selector>
, adicione um item com uma cor padrãocolorOnSurface
à lista de estados. Nas listas de estados, é importante sempre cobrir todos eles. Uma maneira de fazer isso é ter uma cor padrão.
<item android:alpha="0.18" android:color="?attr/colorOnSurface"/>
- Acima da cor padrão, adicione um
item
com a corcolorPrimaryVariant
e restrinja o uso dele a quando o estado selecionado fortrue
. As listas de estados são processadas de cima para baixo, como uma instrução case. Se nenhum dos estados corresponder, o estado padrão será aplicado.
<item android:color="?attr/colorPrimaryVariant"
android:state_selected="true" />
Etapa 2: mostrar a linha de chips
O app GDG cria uma lista de chips mostrando regiões que têm GDGs. Quando um ícone é selecionado, o app filtra os resultados para mostrar apenas os do GDG da região.
- No pacote search, abra GdgListFragment.kt.
- Em
onCreateView()
, logo acima da instruçãoreturn
, adicione um observador emviewModel.regionList
e substituaonChanged()
. Quando a lista de regiões fornecida pelo modelo de visualização muda, os chips precisam ser recriados. Adicione uma instrução para retornar imediatamente se odata
fornecido fornull
.
viewModel.regionList.observe(viewLifecycleOwner, object: Observer<List<String>> {
override fun onChanged(data: List<String>?) {
data ?: return
}
})
- Em
onChanged()
, abaixo do teste nulo, atribuabinding.regionList
a uma nova variável chamadachipGroup
para armazenar em cache oregionList
.
val chipGroup = binding.regionList
- Abaixo, crie um novo
layoutInflator
para inflar chips dechipGroup.context
.
val inflator = LayoutInflater.from(chipGroup.context)
- Limpe e recrie o projeto para se livrar do erro de vinculação de dados.
Abaixo do inflator, agora é possível criar os chips reais, um para cada região no regionList
.
- Crie uma variável,
children
, para armazenar todos os ícones. Atribua a ele uma função de mapeamento nodata
transmitido para criar e retornar cada ícone.
val children = data.map {}
- Dentro da lambda do mapa, para cada
regionName
, crie e insira um ícone. O código completo está abaixo.
val children = data.map {
val children = data.map { regionName ->
val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
chip.text = regionName
chip.tag = regionName
// TODO: Click listener goes here.
chip
}
}
- Dentro do lambda, logo antes de retornar o
chip
, adicione um listener de clique. Quando ochip
for clicado, defina o estado dele comochecked
. ChameonFilterChanged()
noviewModel
, o que aciona uma sequência de eventos que busca o resultado desse filtro.
chip.setOnCheckedChangeListener { button, isChecked ->
viewModel.onFilterChanged(button.tag as String, isChecked)
}
- No final da lambda, remova todas as visualizações atuais do
chipGroup
e adicione todos os ícones dechildren
aochipGroup
. Não é possível atualizar os ícones. Portanto, remova e recrie o conteúdo dochipGroup
.
chipGroup.removeAllViews()
for (chip in children) {
chipGroup.addView(chip)
}
O observador concluído deve ser assim:
override fun onChanged(data: List<String>?) {
data ?: return
val chipGroup = binding.regionList
val inflator = LayoutInflater.from(chipGroup.context)
val children = data.map { regionName ->
val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
chip.text = regionName
chip.tag = regionName
chip.setOnCheckedChangeListener { button, isChecked ->
viewModel.onFilterChanged(button.tag as String, isChecked)
}
chip
}
chipGroup.removeAllViews()
for (chip in children) {
chipGroup.addView(chip)
}
}
})
- Execute o app e pesquise GDGS para abrir a tela Pesquisar e usar os novos chips. Ao clicar em cada ícone, o app vai mostrar os grupos de filtros abaixo dele.
O modo noturno permite que o app mude as cores para um tema escuro, por exemplo, quando as configurações do dispositivo são definidas para ativar o modo noturno. No modo noturno, os apps mudam os planos de fundo claros padrão para escuros e alteram todos os outros elementos da tela de acordo com isso.
Etapa 1: ativar o modo noturno
Para oferecer o tema escuro no seu app, mude o tema de Light
para DayNight
. O tema DayNight
aparece claro ou escuro, dependendo do modo.
- Em
styles.xml,
, mude o tema paiAppTheme
deLight
paraDayNight
.
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
- No método
onCreate()
deMainActivity
, chameAppCompatDelegate.setDefaultNightMode()
para ativar o tema escuro de forma programática.
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
- Execute o app e verifique se ele mudou para o tema escuro.
Etapa 2: gerar sua própria paleta de cores do tema escuro
Para personalizar o tema escuro, crie pastas com o qualificador -night
para o tema escuro usar. Por exemplo, é possível ter cores específicas no modo noturno criando uma pasta chamada values-night
.
- Acesse o seletor de cores do material.io e crie uma paleta de cores para o tema noturno. Por exemplo, você pode usar um azul-escuro.
- Gere e faça o download do arquivo colors.xml.
- Mude para a visualização Arquivos do projeto para listar todas as pastas do projeto.
- Encontre e abra a pasta res.
- Crie uma pasta de recursos res/values-night.
- Adicione o novo arquivo colors.xml à pasta de recursos res/values-night.
- Execute o app, ainda com o modo noturno ativado, e ele vai usar as novas cores definidas para res/values-night. Observe que os ícones usam a nova cor secundária.
Projeto do Android Studio: GDGFinderFinal.
Compatibilidade com idiomas RTL
- No manifesto do Android, defina
android:supportsRtl="true"
. - Você pode conferir uma prévia do RTL no emulador e usar seu próprio idioma para verificar os layouts de tela. Em um dispositivo ou emulador, abra as Configurações e, em Opções do desenvolvedor, selecione Forçar layout da direita p/ esquerda.
- Substitua as referências a
Left
eRight
por referências aStart
eEnd
. - Exclua
android:autoMirrored="true"
para desativar o espelhamento de elementos gráficos. - Escolha Refactor > Add RTL support where possible para deixar o Android Studio fazer o trabalho por você.
- Use pastas values-"código do idioma" para armazenar recursos específicos de idiomas.
Verificar a acessibilidade
- Na Play Store, baixe e execute o Scanner de acessibilidade do Google LLC para verificar elementos da tela que podem ser melhorados.
Projetar para o TalkBack com descrições de conteúdo
- Instale o Pacote de Acessibilidade do Android, do Google, que inclui o TalkBack.
- Adicione descrições de conteúdo a todos os elementos da interface. Exemplo:
android:contentDescription="@string/stage_image_description"
- Para um elemento editável, como um
EditText
, use um atributoandroid:hint
no XML para dar uma dica ao usuário sobre o que digitar. - Crie grupos de conteúdo agrupando elementos relacionados em um grupo de visualização.
- Crie uma região dinâmica para dar aos usuários feedback adicional com
android:accessibilityLiveRegion
.
Usar ícones para implementar um filtro
- Chips são elementos compactos que representam um atributo, texto, entidade ou ação.
- Para criar um grupo de chips, use um
com.google.android.material.chip.ChipGroup
. - Defina o layout para um
com.google.android.material.chip.Chip
. - Se quiser que os ícones mudem de cor, forneça uma lista de estados de cor como um
<selector>
com cores com estado:<item android:color="?attr/colorPrimaryVariant"
android:state_selected="true" /> - Vincule os ícones aos dados ativos adicionando um observador aos dados no modelo de visualização.
- Para mostrar os ícones, crie um inflador para o grupo de ícones:
LayoutInflater.from(chipGroup.context)
- Crie os ícones, adicione um listener de clique que aciona a ação desejada e adicione os ícones ao grupo.
Suporte para o modo escuro
- Use
DayNight
AppTheme
para oferecer suporte ao modo escuro. - Você pode definir o modo escuro de forma programática:
AppCompatDelegate.setDefaultNightMode()
- Crie uma pasta de recursos res/values-night para fornecer cores e valores personalizados para o modo escuro.
Documentação do desenvolvedor Android:
LayoutDirection
(RTL)- Bidirecionalidade
- Introdução ao Scanner de acessibilidade
- TalkBack
- Gestos do TalkBack
- Documentos de visão geral de drawables
- Descritores de conteúdo
- Agrupamento de conteúdo
- Regiões dinâmicas
- Drawables NinePatch
- Ferramenta Draw 9-patch
- Ícones
ChipGroup
- Tema escuro
- Temas de cor
- Ferramenta de cores
- Animar gráficos drawable
Outros recursos:
- Desenvolver apps Android com Kotlin (curso da Udacity em inglês)
- Bootcamp de Kotlin para programadores (curso da Udacity)
- Codelabs do Bootcamp de Kotlin para programadores
Esta seção lista as possíveis atividades de dever de casa para os alunos que estão fazendo este codelab como parte de um curso ministrado por um professor. Cabe ao professor fazer o seguinte:
- Atribuir o dever de casa, se necessário.
- Informar aos alunos como enviar deveres de casa.
- Atribuir nota aos deveres de casa.
Os professores podem usar essas sugestões o quanto quiserem, podendo passar os exercícios que acharem mais apropriados como dever de casa.
Se você estiver seguindo este codelab por conta própria, sinta-se à vontade para usar esses deveres de casa para testar seu conhecimento.
Pergunta 1
Qual das opções abaixo é obrigatória para oferecer suporte a idiomas com direção de leitura da direita para a esquerda (RTL)?
▢ Substitua Left
e Right
nas propriedades por Start
e End
.
▢ Trocar para um idioma da direita para a esquerda (RTL)
▢ Verifique se todos os ícones usam android:autoMirrored="true"
▢ Fornecer descrições de conteúdo
Pergunta 2
Quais das ferramentas de acessibilidade abaixo são integradas à maioria dos dispositivos Android?
▢ TalkBack
▢ Scanner de acessibilidade
▢ No Android Studio, Refactor > Add RTL support where possible
▢ Lint
Pergunta 3
Qual das seguintes opções não é verdadeira sobre os chips?
▢ Você mostra ícones como parte de um ChipGroup
.
▢ É possível fornecer uma lista de estados de cor para um ChipGroup
.
▢ Os ícones são elementos compactos que representam uma entrada, um atributo ou uma ação.
▢ Sempre ative DarkTheme
se o app usar chips.
Pergunta 4
Qual tema oferece estilos para os modos escuro e claro?
▢ DayNight
▢ DarkTheme
▢ DarkAndLightTheme
▢ Light
Pergunta 5
O que é uma região ativa?
▢ Um nó que contém informações importantes para o usuário
▢ Uma região da tela que muda de forma de acordo com as diretrizes do Material.
▢ Uma visualização que permite o streaming de vídeo
▢ Um drawable animado