Adicionar compatibilidade com teclado, mouse, trackpad e stylus com o Jetpack Compose

1. Introdução

Assim que fica disponível para smartphones padrão, seu app também fica disponível para dispositivos de tela grande, como tablets, dobráveis e dispositivos ChromeOS.

Os usuários esperam que seu app ofereça uma experiência em telas grandes equivalente ou até melhor que a UX em telas pequenas.

Em dispositivos de tela grande, os usuários também têm mais chances de usar o app com um teclado físico e um dispositivo apontador, como um mouse ou trackpad. Alguns dispositivos de tela grande, como os Chromebooks, incluem um teclado físico e um dispositivo apontador. Outros se conectam a teclados e dispositivos apontadores por USB ou Bluetooth. Os usuários esperam usar teclados físicos e dispositivos apontadores para realizar as mesmas tarefas no seu app que fariam com touch screens.

Pré-requisitos

  • Experiência na criação de apps com o Compose
  • Conhecimento básico de Kotlin, incluindo lambdas e corrotinas

O que você vai criar

Vamos adicionar compatibilidade com teclado físico e mouse a um app baseado no Jetpack Compose. As etapas são estas:

  1. Seguir os critérios definidos nas diretrizes de qualidade de apps para telas grandes
  2. Analisar o resultado da auditoria e descobrir os problemas relacionados à compatibilidade com teclado físico e mouse
  3. Corrigir os problemas

Mais especificamente, você vai atualizar o app de exemplo com o seguinte:

  • Navegação pelo teclado
  • Atalho de teclado para rolar para baixo e para cima
  • Assistente de atalhos do teclado

O que você vai aprender

  • Como auditar seu app para identificar compatibilidade com dispositivos virtuais
  • Como gerenciar a navegação pelo teclado com o Compose
  • Como adicionar atalhos do teclado com o Compose

O que você precisa

  • Android Studio Hedgehog ou mais recente
  • Qualquer um destes dispositivos para executar o app de exemplo:
  • Um dispositivo de tela grande com um teclado físico e um mouse
  • Um Dispositivo virtual Android com um perfil definido na categoria de dispositivo desktop

2. Configurar

  1. Clone o repositório do GitHub para codelabs de tela grande:
git clone https://github.com/android/large-screen-codelabs

Como alternativa, você pode baixar e extrair o arquivo ZIP para codelabs de tela grande:

  1. Navegue até a pasta add-keyboard-and-mouse-support-with-compose.
  2. No Android Studio, abra o projeto. A pasta add-keyboard-and-cursor-support-with-compose contém um projeto.
  3. Se você não tem um tablet Android ou dispositivos dobráveis, ou um dispositivo ChromeOS com teclado físico e mouse, abra o Gerenciador de dispositivos no Android Studio e crie um dos dispositivos virtuais na categoria Desktop.

Dispositivos virtuais na categoria Desktop

3. Explorar o app

O app de exemplo mostra uma lista de artigos. Os usuários poderão ler um artigo selecionado na lista.

O app atualiza o layout de maneira adaptativa de acordo com a largura da janela. Há três classes para classificar a largura da janela do app: compacta, média e expandida.

Classes de tamanho de janela por largura: compacta, média e expandida. Se a janela do aplicativo tem menos de 600 dp, a largura é classificada como compacta. A largura da janela é classificada como expandida quando é maior ou igual a 640 dp. Se a janela não pertencer à classe compacta nem expandida, a janela será média.

Layout para as classes de tamanho de janela compacta e média

O app usa um layout de painel único. Na tela inicial, o app mostra uma lista de artigos. Quando o usuário seleciona um artigo na lista, uma transição de tela acontece e o artigo é mostrado.

A navegação global é implementada com uma gaveta de navegação (link em inglês).

O app está sendo executado em um emulador de computador em uma janela compacta. A lista de artigos é mostrada.

Layout para a classe de tamanho de janela expandida

O app usa um layout de detalhes e listas. O painel de listas mostra uma lista de artigos. O painel de detalhes mostra o artigo selecionado.

A navegação global é implementada com uma coluna de navegação (link em inglês).

O app está sendo executado em um emulador de computador em uma classe de tamanho de janela expandida.

4. Contexto

O Compose oferece várias APIs para ajudar o app a processar eventos do teclado físico e do mouse. Algumas APIs permitem o processamento de eventos de teclado e mouse de maneira semelhante ao processamento de eventos de toque. Como resultado, para muitos casos de uso, seu app é compatível com teclado físico e mouse sem nenhum esforço de desenvolvimento da sua parte.

Um exemplo típico é o modificador clickable, que permite a detecção de cliques. Um toque com o dedo é detectado como um clique. Um clique do mouse e o pressionamento da tecla Enter também são detectados como cliques. Se o app detecta cliques com o modificador clickable, então também permite que os usuários interajam com componentes, independente do dispositivo de entrada.

No entanto, apesar do alto nível de compatibilidade das APIs, ainda é necessário trabalho de desenvolvimento para oferecer compatibilidade com teclado físico e mouse. Um dos motivos é a necessidade de descobrir os casos específicos testando seu app. Também é necessário algum esforço para reduzir o atrito do usuário decorrente das características dos dispositivos, como:

  • Os usuários não sabem em quais componentes podem clicar
  • Os usuários não conseguem mover o foco do teclado como esperado
  • Os usuários não conseguem rolar para cima ou para baixo usando o teclado físico

Foco do teclado

O foco do teclado é a principal diferença entre a interação com o teclado físico e os toques na tela. Os usuários podem tocar em qualquer componente na tela, independente da posição do componente em que tocaram anteriormente. Por outro lado, com teclados, os usuários precisam selecionar o componente com que vão interagir antes do início da interação. A seleção é chamada de foco do teclado.

Os usuários podem mover o foco do teclado com a tecla Tab e as teclas de direção (ou seta). O foco do teclado se move apenas para os componentes vizinhos por padrão.

A maior parte do atrito do teclado físico está relacionada ao foco do teclado. A lista abaixo mostra os problemas comuns:

  • Os usuários não conseguem mover o foco do teclado para o componente com que querem interagir.
  • O componente não detecta cliques quando os usuários pressionam a tecla Enter.
  • O foco do teclado se move de maneira diferente da expectativa do usuário.
  • Os usuários precisam pressionar várias teclas para mover o foco do teclado para o componente com que querem interagir após as transições de tela.
  • Os usuários não conseguem determinar qual componente está com o foco do teclado porque nenhum sinal visual indica isso.
  • Os usuários não conseguem determinar o componente padrão em foco ao navegar para uma nova tela.

A indicação visual do foco do teclado é importante. Caso contrário, os usuários podem se perder no app e não entenderão o que acontece quando pressionam a tecla Enter. O destaque é um sinal visual típico para indicar o foco do teclado. Os usuários podem perceber que o botão no card direito está em foco no teclado porque ele está em destaque.

53ee7662b764f2dd.png

Atalhos do teclado

Os usuários esperam poder usar atalhos de teclado comuns ao navegar no seu app com um teclado físico. Alguns componentes ativam atalhos de teclado comuns por padrão. BasicTextField é um exemplo típico. Ele permite que os usuários utilizem atalhos de teclado padrão de edição de texto, incluindo o seguinte:

Atalho

Recurso

Ctrl+C

Copiar

Ctrl+X

Cortar

Ctrl+V

Colar

Ctrl+Z

Desfazer

Ctrl+Y

Refazer

Seu app pode adicionar atalhos de teclado processando eventos de tecla. Os modificadores onKeyEvent e onPreviewKeyEvent permitem monitorar esses eventos.

Dispositivos apontadores: mouse, trackpad e stylus

O app pode processar mouse, trackpad e stylus da mesma maneira. Um toque no trackpad é detectado como um clique com o modificador clickable. Um toque com a stylus também é detectado como um clique.

É importante que os usuários entendam visualmente se podem clicar em um componente ou não. É por isso que o estado de passar cursor é mencionado nas diretrizes de qualidade de apps para telas grandes.

Os componentes do Material3 são compatíveis com o estado de passar cursor por padrão. O Material 3 oferece o efeito visual do estado de passar cursor. Você pode aplicá-lo ao componente interativo com o modificador indication.

Rolagens

Os contêineres roláveis são compatíveis com a rolagem da roda do mouse, gestos de rolagem no trackpad e rolagem com as teclas PageUp e PageDown por padrão.

Para a rolagem horizontal, seu app seria muito mais fácil de usar se mostrasse botões de seta para a esquerda e para a direita no estado de passar cursor, para que os usuários pudessem rolar o conteúdo clicando nos botões.

17feb4d3bf08831e.png

Mudanças de configuração por conexão e desconexão de dispositivos

Os usuários podem conectar ou desconectar um teclado e um mouse enquanto o app está em execução. Os usuários podem conectar um teclado físico quando encontrarem um campo para inserir uma grande quantidade de texto. Um mouse conectado por Bluetooth se desconecta quando entra no modo de espera. Um teclado conectado por USB pode ser desconectado por engano.

A conexão ou desconexão do hardware periférico aciona mudanças na configuração. O app precisa manter o estado durante as mudanças de configuração. Para mais informações, consulte Salvar estados da interface.

5. Testar o app de exemplo com teclado e mouse

Para começar o desenvolvimento de compatibilidade com teclado físico e mouse, inicie o app de exemplo e confirme o seguinte:

  • Os usuários precisam conseguir mover o foco do teclado para todos os componentes interativos.
  • Os usuários precisam poder "clicar" no componente em foco com a tecla Enter.
  • Os componentes interativos precisam mostrar uma indicação quando recebem o foco do teclado.
  • O foco do teclado se move conforme o esperado pelo usuário (ou seja, de acordo com as convenções estabelecidas) usando a tecla Tab, Shift+Tab e as teclas direcionais (seta).
  • Os componentes interativos precisam ter um estado de passar cursor.
  • Os usuários precisam conseguir clicar nos componentes interativos.
  • O menu de contexto aparece ao clicar com o botão direito do mouse (controle secundário) nos componentes apropriados, como aqueles em que o menu de contexto aparece com um toque longo ou uma seleção de texto.

Você precisará passar por todos os itens duas vezes neste codelab: uma para o layout de painel único e outra para o layout de detalhes e listas.

Problemas que precisam ser corrigidos neste codelab

Você vai encontrar problemas. Neste codelab, vamos corrigir o seguinte:

  • Os usuários não conseguem ler o artigo inteiro apenas com o teclado físico porque não conseguem rolar a página para baixo.
  • Os usuários não podem determinar se o painel de detalhes está com o foco do teclado ou não.

6. Permitir que os usuários leiam o artigo inteiro no painel de detalhes

O painel de detalhes mostra o artigo selecionado. Alguns artigos são muito longos para serem lidos sem rolar a tela. No entanto, os usuários não conseguem rolar para cima e para baixo no artigo apenas com o teclado físico.

4627289223e5cfbc.gif

Os contêineres roláveis, como LazyColumn, permitem que os usuários rolem para baixo com a tecla PageDown. A causa raiz do problema é que os usuários não conseguem mover o foco do teclado para o painel de detalhes.

O componente deve ser capaz de obter o foco do teclado para receber um evento de teclado. O modificador focusable permite que o componente modificado receba o foco do teclado.

Para corrigir esse problema, siga estas etapas:

  1. Acesse a função combinável PostContent no arquivo ui/article/PostContent.kt.
  2. Mude a função combinável LazyColumn com o modificador focusable.
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
    post: Post,
    modifier: Modifier = Modifier,
    contentPadding: PaddingValues = PaddingValues(0.dp),
    state: LazyListState = rememberLazyListState(),
    coroutineScope: CoroutineScope = rememberCoroutineScope(),
    focusRequester: FocusRequester = remember { FocusRequester() },
    header: (@Composable () -> Unit)? = null
) {
    LazyColumn(
        contentPadding = contentPadding,
        modifier = modifier
            .padding(horizontal = defaultSpacerSize)
            .focusable(),
        state = state,
    ) {
      // Code to layout the selected article.
    }
}

Indicar que o artigo tem foco do teclado

Agora, os usuários podem ler o artigo inteiro rolando a página para baixo com a tecla PageDown. No entanto, é difícil para eles entenderem se o componente PostContent está com o foco do teclado ou não porque nenhum efeito visual indica isso.

O app pode indicar visualmente o foco do teclado associando uma Indication a componentes. Uma indicação cria um objeto para renderizar efeitos visuais de acordo com as interações. Por exemplo, a indicação padrão do Material 3 destaca o componente quando ele tem o foco do teclado.

O app de exemplo tem uma Indication com o nome BorderIndication. A indicação mostra uma linha ao lado do componente com foco do teclado (como na captura de tela a seguir). O código é armazenado no arquivo ui/components/BorderIndication.kt.

Uma linha cinza-claro aparece na lateral do artigo quando ele está com o foco do teclado.

Para fazer com que o elemento combinável PostConent mostre a BorderIndication quando o foco do teclado estiver ativado, siga estas etapas:

  1. Acesse a função combinável PostContent no arquivo ui/article/PostContent.kt.
  2. Declare o valor interactionSource associado ao valor de retorno da função remember().
  3. Chame a função MutableInteractionSource() na função remember() para que o objeto MutableInteractionSource criado seja associado ao valor interactionSource.
  4. Transmita o valor interactionSource ao modificador focusable usando o parâmetro interactionSource.
  5. Mude o modificador do elemento combinável PostContent para chamar o modificador focusable após a invocação do modificador indication.
  6. Transmita o valor interactionSource e o valor de retorno da função BorderIndication ao modificador da indicação.
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
    post: Post,
    modifier: Modifier = Modifier,
    contentPadding: PaddingValues = PaddingValues(0.dp),
    state: LazyListState = rememberLazyListState(),
    coroutineScope: CoroutineScope = rememberCoroutineScope(),
    focusRequester: FocusRequester = remember { FocusRequester() },
    header: (@Composable () -> Unit)? = null
) {
    val interactionSource = remember { MutableInteractionSource() }

    LazyColumn(
        contentPadding = contentPadding,
        modifier = modifier
            .padding(horizontal = defaultSpacerSize)
            .indication(interactionSource, BorderIndication())
            .focusable(interactionSource = interactionSource),
        state = state,
    ) {
      // Code to layout the selected article.
    }
}

Adicionar atalhos de teclado para rolar para cima e para baixo

É um recurso comum permitir que os usuários rolem para cima e para baixo com a Spacebar. Seu app pode implementar o recurso adicionando um atalho de teclado como a tabela abaixo:

Atalho

Recurso

Spacebar

Rolar o artigo para baixo

Shift + Spacebar

Rolar o artigo para cima

O modificador onKeyEvent permite que o app processe eventos de tecla que ocorrem em um componente modificado. O modificador usa uma lambda chamada com um objeto KeyEvent que descreve o evento de tecla. A lambda precisa retornar um valor Boolean indicando se o evento de tecla foi consumido.

A posição de rolagem de uma LazyColumn e uma LazyRow é capturada em um objeto LazyListState. Seu app pode acionar a rolagem chamando o método de suspensão animateScrollBy() no objeto LazyListState. O método rola a LazyColumn para baixo pelo número especificado de pixels. Quando a função de suspensão é chamada com um valor flutuante negativo, ela rola a tela para cima na LazyColumn.

Para implementar esses atalhos de teclado, siga estas etapas:

  1. Acesse a função combinável PostContent no arquivo ui/article/PostContent.kt.
  2. Modifique a função combinável LazyColumn com o modificador onKeyEvent.
  3. Adicione uma expressão if à lambda transmitida ao modificador onKeyEvent desta forma:
  • Retorne true se as condições abaixo forem atendidas:
  • A Spacebar for pressionada. Para detectar isso, teste se o atributo type é KeyType.KeyDown e o atributo key é Key.Spacebar.
  • O atributo isCtrlPressed é "false" (falso) para garantir que a tecla Ctrl não esteja pressionada.
  • O atributo isAltPressed é "false" para garantir que a tecla Alt não esteja pressionada.
  • O atributo isMetaPressed é "false" para garantir que a tecla Meta (consulte a observação) não esteja pressionada.
  • Caso contrário, retorne false.
  1. Determine a rolagem com o valor de Spacebar desta forma:
  • -0.4f quando a tecla Shift é pressionada, o que é descrito pelo atributo isShiftPressed do objeto KeyEvent.
  • Caso contrário, 0.4f.
  1. Chame o método launch() no coroutineScope, que é um parâmetro da função combinável PostContent.
  2. Calcule a quantidade real de rolagem multiplicando o valor de rolagem relativo calculado na etapa anterior e o atributo state.layoutInfo.viewportSize.height no parâmetro lambda do método launch. O atributo representa a altura da LazyColumn, chamada na função combinável PostContent.
  3. Chame o método state.animateScrollBy() na lambda para o método launch() acionar a rolagem vertical.
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
    post: Post,
    modifier: Modifier = Modifier,
    contentPadding: PaddingValues = PaddingValues(0.dp),
    state: LazyListState = rememberLazyListState(),
    coroutineScope: CoroutineScope = rememberCoroutineScope(),
    focusRequester: FocusRequester = remember { FocusRequester() },
    header: (@Composable () -> Unit)? = null
) {
    val interactionSource = remember { MutableInteractionSource() }

    LazyColumn(
        contentPadding = contentPadding,
        modifier = modifier
            .padding(horizontal = defaultSpacerSize)
            .onKeyEvent {
                if (
                    it.type == KeyEventType.KeyDown &&
                    it.key == Key.Spacebar &&
                    !it.isCtrlPressed &&
                    !it.isAltPressed &&
                    !it.isMetaPressed
                ) {

                    val relativeAmount = if (it.isShiftPressed) {
                        -0.4f
                    } else {
                        0.4f
                    }
                    coroutineScope.launch {
                        state.animateScrollBy(relativeAmount * state.layoutInfo.viewportSize.height)
                    }
                    true
                } else {
                    false
                }
            }
            .indication(interactionSource, BorderIndication())
            .focusable(interactionSource = interactionSource),
        state = state,
    ) {
      // Code to layout the selected article.
    }
}

Informar os atalhos de teclado aos usuários

Os usuários não podem aproveitar ao máximo o teclado adicionado se não conhecerem os atalhos. O app pode informar aos usuários os atalhos disponíveis com o assistente de atalhos do teclado, que faz parte da interface do sistema Android. Os usuários podem abrir o assistente de atalhos com Meta+/.

O assistente de atalhos do teclado mostra os atalhos adicionados na seção anterior.

O app substitui o método onProvideKeyboardShortcuts() na atividade principal para fornecer uma lista de atalhos para o assistente de atalhos do teclado.

Mais especificamente, o app fornece vários objetos KeyboardShortcutGroup adicionando-os à lista mutável transmitida para onProvideKeyboardShortcuts(). Cada KeyboardShortcutGroup representa uma categoria nomeada de atalhos de teclado, o que permite que o app agrupe os atalhos disponíveis por finalidade ou contexto.

O app de exemplo tem dois atalhos de teclado, Spacebar e Shift+Spacebar.

Para disponibilizar esses dois atalhos no assistente, siga estas etapas:

  1. Abra o arquivo MainActivity.kt.
  2. Substitua o método onProvideKeyboardShortcuts() em MainActivity.
  3. Confira se a versão do SDK do Android é o Android 7.0 (nível 24 da API) ou mais recente para que o assistente de atalhos de teclado esteja disponível.
  4. Confirme se o primeiro parâmetro do método não é null.
  5. Crie um objeto KeyboardShortcutInfo para a tecla Spacebar com os parâmetros abaixo:
  • Texto de descrição
  • android.view.KeyEvent.KEYCODE_SPACE
  • 0 (indica que não há modificadores)
  1. Crie outras KeyboardShortcutInfo para Shift+Spacebar com os parâmetros abaixo:
  • Texto de descrição
  • android.view.KeyEvent.KEYCODE_SPACE
  • android.view.KeyEvent.META_SHIFT_ON
  1. Crie uma lista imutável contendo os dois objetos KeyboardShortcutInfo.
  2. Crie um objeto KeyboardShortcutGroup com os parâmetros abaixo:
  • Nome do grupo no texto
  • A lista imutável da etapa anterior
  1. Adicione o objeto KeyboardShortcutGroup à lista mutável transmitida como o primeiro parâmetro do método onProvideKeyboardShortcuts().

O método substituído tem esta aparência:

   override fun onProvideKeyboardShortcuts(
        data: MutableList<KeyboardShortcutGroup>?,
        menu: Menu?,
        deviceId: Int
    ) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && data != null) {
            val shortcutGroup = KeyboardShortcutGroup(
                "To read articles",
                listOf(
                    KeyboardShortcutInfo("Scroll down", KeyEvent.KEYCODE_SPACE, 0), // 0 means no modifier key is pressed
                    KeyboardShortcutInfo("Scroll up", KeyEvent.KEYCODE_SPACE, KeyEvent.META_SHIFT_ON),
                )
            )
            data.add(shortcutGroup)
        }
    }

Executar

Agora, os usuários podem ler o artigo inteiro, mesmo rolando com a Spacebar. Para testar, mova o foco do teclado para o artigo com a tecla Tab ou teclas direcionais. Uma mensagem incentivando você a clicar na Spacebar vai aparecer.

O assistente de atalhos do teclado mostra os dois atalhos que você adicionou (pressione Meta+/). Os atalhos adicionados são listados na guia App atual.

7. Simplificar a navegação pelo teclado no painel de detalhes

Os usuários precisam pressionar a tecla Tab várias vezes para mover o foco do teclado para o painel de detalhes quando o app estiver sendo executado na classe de tamanho de janela expandida. Com a tecla direcional direita, os usuários podem mover o foco do teclado da lista de artigos para o artigo com uma única ação, mas ainda precisam mover o foco do teclado. O foco inicial é incompatível com o objetivo principal do usuário, que é ler os artigos.

O app pode pedir para mover o foco do teclado para o componente específico com um objeto FocusRequester. O modificador focusRequester associa um objeto FocusRequester ao componente modificado. Seu app pode enviar o pedido real para o movimento de foco chamando o método requestFocus() do objeto FocusRequester.

O envio de uma solicitação para mover o foco do teclado é um efeito colateral do componente. O app precisa chamar o método da maneira correta usando a função LaunchedEffect.

Para definir o elemento combinável PostContent para receber o foco do teclado quando os usuários selecionam um artigo na lista, siga estas etapas:

  1. Acesse a função combinável PostContent no arquivo ui/article/ PostContent.kt.
  2. Associe o valor focusRequester à função combinável LazyColumn com o modificador focusRequester. O valor focusRequester é especificado como um parâmetro opcional da função combinável PostContent.
  3. Chame LaunchedEffect com post, o primeiro parâmetro da função combinável PostContent, para que a lambda transmitida seja chamada quando o usuário selecionar um artigo.
  4. Chame o método focusRequester.requestFocus() na lambda transmitida para a função LaunchedEffect.

O elemento combinável PostContent atualizado fica assim:

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
    post: Post,
    modifier: Modifier = Modifier,
    contentPadding: PaddingValues = PaddingValues(0.dp),
    state: LazyListState = rememberLazyListState(),
    coroutineScope: CoroutineScope = rememberCoroutineScope(),
    focusRequester: FocusRequester = remember { FocusRequester() },
    header: (@Composable () -> Unit)? = null
) {
    val interactionSource = remember { MutableInteractionSource() }

    LaunchedEffect(post) {
        focusRequester.requestFocus()
    }

    LazyColumn(
        contentPadding = contentPadding,
        modifier = modifier
            .padding(horizontal = defaultSpacerSize)
            .onKeyEvent {
                if (it.type == KeyEventType.KeyDown && it.key == Key.Spacebar) {
                    val relativeAmount = if (it.isShiftPressed) {
                        -0.4f
                    } else {
                        0.4f
                    }
                    coroutineScope.launch {
                        state.animateScrollBy(relativeAmount * state.layoutInfo.viewportSize.height)
                    }
                    true
                } else {
                    false
                }
            }
            .focusRequester(focusRequester),
            .indication(interactionSource, BorderIndication())
            .focusable(interactionSource = interactionSource),
        state = state,
    ) {
      // Code to layout the selected article.
    }
}

Executar

Agora, o foco do teclado se move para o artigo quando os usuários escolhem um artigo da lista. A mensagem incentiva o uso de Spacebar para rolar a tela para baixo ao escolher um artigo.

8. Parabéns

Muito bem! Você adicionou compatibilidade com teclado físico e mouse ao app de exemplo. Assim, os usuários podem selecionar e ler um artigo da lista usando apenas um teclado ou mouse físico.

Você aprendeu o seguinte para adicionar compatibilidade com teclado físico e mouse:

  • Como conferir se o app é compatível com teclado físico e mouse, inclusive com um emulador
  • Como gerenciar a navegação pelo teclado com o Compose
  • Como adicionar atalhos do teclado com o Compose

Você também adicionou compatibilidade com teclado físico e mouse com uma pequena modificação no código.

Agora você já pode implementar o que aprendeu ao seu app de produção com o Compose.

E, com um pouco mais de aprendizado, você pode adicionar atalhos de teclado a estes recursos:

  • Marcar o artigo selecionado como "Gostei".
  • Adicionar o artigo selecionado aos favoritos.
  • Compartilhar o artigo selecionado com outros apps.

Saiba mais