No Wear OS 7 (nível 37 da API) e versões mais recentes, uma estrutura de gestos com uma mão, junto com uma API que faz parte do Compose para Wear OS, permite que os usuários interajam com o app sem tocar na tela.
Embora inicialmente tenha sido compatível com dispositivos Pixel Watch (Pixel Watch 3 e mais recentes), o framework está disponível para todos os OEMs. Ao adotar essa API, o suporte a gestos do seu app é escalonado automaticamente em todo o ecossistema à medida que o suporte a hardware aumenta.
Para ajudar os usuários a descobrir os gestos disponíveis sem poluir a interface, o framework do Wear OS oferece indicadores de gestos animados. Essas dicas visuais destacam onde um gesto pode ser realizado, enquanto o sistema gerencia automaticamente a cadência de exibição e a frequência de silenciamento de acordo com as preferências do usuário.
Gestos e ações compatíveis
A estrutura de gestos do Wear OS oferece suporte a dois tipos de gestos:
- Ação principal (fazer gesto de pinça duas vezes): mapeia a ação principal em uma tela, como atender uma ligação ou alternar a reprodução de mídia.
- Ação de dispensar (girar o pulso): mapeia a navegação para trás, dispensando uma caixa de diálogo ou cancelando um comando.
Configurar gestos no Compose
Embora a API de gestos com uma mão possa melhorar sua interface, é importante lembrar que alguns hardwares e OEMs não oferecem suporte a esses gestos. Se a API detectar que o app está sendo executado em um desses dispositivos não compatíveis, a biblioteca vai gerar uma operação nula automática sem afetar as interações de toque padrão.
Assim como nos comportamentos padrão do Compose, você ativa gestos com uma mão em elementos
da interface usando modificadores. Você configura os gestos do app
de acordo com a ação a ser realizada (principal ou dispensar) e um gestureId
para coordenar com as preferências do usuário no nível do sistema, como a cadência de exibição de dicas
e a frequência de silenciamento. Para expressar essa configuração, crie um objeto OneHandedGestureConfiguration. Recomendamos usar a função rememberOneHandedGestureConfiguration para isso. O
OneHandedGestureConfiguration também é onde você pode fornecer a prioridade
do gesto.
A função rememberOneHandedGestureConfiguration rastreia o histórico de interação do usuário
em recomposições sem expor o estado do aplicativo. Depois que o
app criar a configuração, ele vai transmitir a configuração para
Modifier.oneHandedGesture no elemento combinável interativo.
Para ajudar os usuários a descobrir os gestos disponíveis, a biblioteca oferece o método
OneHandedGestureClickIndicator. Esse método atua como um wrapper que
substitui o conteúdo subjacente para indicar ao usuário que uma ação de gesto
está disponível.
Componentes interativos
Para ativar gestos em um controle interativo, como um botão, crie uma
configuração especificando OneHandedGestureAction.Primary e aplique o
modificador oneHandedGesture. Transmita o mesmo MutableInteractionSource para o controle e o modificador para que os eventos de gestos emitam feedback de pressionamento visual no controle.
Para ativar o indicador de gesto, crie e lembre-se de uma instância de
OneHandedGestureClickIndicatorState. Em seguida, para acionar o feedback visual,
chame showIndicator no callback onGestureAvailable fornecido pelo
modificador oneHandedGesture, que sinaliza ao sistema que um evento
de indicação ocorreu. Depois de ser chamado, o componente substitui brevemente o conteúdo
normal por uma animação de gesto.
var isPlaying by remember { mutableStateOf(false) } val onClick = { isPlaying = !isPlaying } val gestureConfig = rememberOneHandedGestureConfiguration( action = OneHandedGestureAction.Primary ) val indicatorState = remember { OneHandedGestureClickIndicatorState() } val coroutineScope = rememberCoroutineScope() val interactionSource = remember { MutableInteractionSource() } Button( onClick = onClick, interactionSource = interactionSource, modifier = Modifier .fillMaxWidth() .oneHandedGesture( gestureConfiguration = gestureConfig, interactionSource = interactionSource, onGestureLabel = if (isPlaying) "pause" else "play", onGestureAvailable = { coroutineScope.launch { indicatorState.showIndicator() } }, onGesture = onClick ) ) { OneHandedGestureClickIndicator( gestureConfiguration = gestureConfig, state = indicatorState ) { Text(if (isPlaying) "Pause" else "Play", modifier = Modifier.fillMaxWidth()) } }
Contêineres roláveis
Para telas ou listas roláveis, crie uma configuração especificando
OneHandedGestureAction.Primary e aplique o modificador oneHandedGesture ao
contêiner, chamando um auxiliar de rolagem, como scrollDown.
Para fornecer feedback visual para ações de rolagem, use o
OneHandedGestureScrollIndicator. Esse componente funciona como um indicador de rolagem padrão que mostra a posição de rolagem, mas também pode indicar que um gesto de rolagem está disponível para o usuário. Esse indicador geralmente é transmitido ao slot scrollIndicator de um ScreenScaffold e é associado ao estado de um contêiner rolável, como um TransformingLazyColumn. Ele também observa um
OneHandedGestureScrollIndicatorState para gerenciar as transições visuais.
Para acionar o feedback visual, chame showIndicator nesse estado, geralmente
dentro do callback onGestureAvailable do modificador oneHandedGesture.
Quando acionado, o indicador substitui temporariamente o estado visual padrão
por uma sequência de animação de gestos para alertar o usuário.
val scrollState = rememberTransformingLazyColumnState() val gestureConfig = rememberOneHandedGestureConfiguration( action = OneHandedGestureAction.Primary, priority = OneHandedGesturePriority.Scrollable ) val indicatorState = remember(gestureConfig) { OneHandedGestureScrollIndicatorState() } val coroutineScope = rememberCoroutineScope() ScreenScaffold( scrollState = scrollState, scrollIndicator = { OneHandedGestureScrollIndicator( gestureConfiguration = gestureConfig, indicatorState = indicatorState, scrollState = scrollState, modifier = Modifier.align(Alignment.CenterEnd) ) } ) { contentPadding -> TransformingLazyColumn( state = scrollState, contentPadding = contentPadding, modifier = Modifier .fillMaxSize() .oneHandedGesture( gestureConfiguration = gestureConfig, onGestureLabel = "scroll", onGestureAvailable = { coroutineScope.launch { indicatorState.showIndicator() } }, onGesture = { OneHandedGestureDefaults.scrollDown(scrollState) } ) ) { items(10) { index -> Text("Item $index", modifier = Modifier.padding(8.dp)) } } }
Combinar vários gestos
É possível configurar um gesto de rolagem e um gesto de clique com a mesma
ação principal adicionando gesturePriority ao objeto
OneHandedGestureConfiguration:
OneHandedGesturePriority.Clickable(mais alto): atribua a controles interativos, como aqueles com tipoButtonouCard, para que eles capturem gestos quando estiverem visíveis na tela.OneHandedGesturePriority.Scrollable(médio): atribua a contêineres roláveis ou pagináveis para que eles cedam a filhos clicáveis, mas rolem quando nenhum controle clicável estiver visível.OneHandedGesturePriority.Unspecified(mais baixa): uma prioridade não atribuída. Esse é o valor padrão para um gesto que não tem umprioritydefinido.
Ao definir explicitamente priority = OneHandedGesturePriority.Clickable
em um botão interno e priority = OneHandedGesturePriority.Scrollable
na lista principal, o sistema pode mostrar esse comportamento de prioridade de gesto.
Quando o usuário aciona a ação principal com o gesto de uma mão, a lista rola para baixo até que o botão fique visível e, em seguida, captura a ação de clique do botão.
Testar e depurar gestos com o ADB
É possível testar gestos com uma mão em um dispositivo físico ou emulador
sem fazer movimentos físicos do pulso usando o Android Debug
Bridge (adb) e o serviço do sistema IWearGestureService.
Ativar simulação de gestos
Antes de simular gestos usando o ADB, configure as configurações do dispositivo e as substituições de restrições:
Verifique se o dispositivo Wear OS está executando o Wear OS 7 (nível 37 da API) ou uma versão mais recente:
adb shell getprop ro.build.version.sdkSe você estiver testando em um dispositivo físico que não está no pulso ou está em um carregador, substitua a restrição fora do corpo para que a estrutura de gestos permaneça ativa:
adb shell cmd IWearGestureService override-constraints offbody-state
Acionar eventos de gestos usando o ADB
Para simular o gesto de fazer gesto de pinça duas vezes (que é a ação Primary em relógios Pixel), execute o seguinte comando do shell ADB:
adb shell cmd IWearGestureService gesture DoublePinch
Para simular o gesto de Girar o pulso (que é a ação Dismiss em relógios Pixel), execute o seguinte comando do shell ADB:
adb shell cmd IWearGestureService gesture WristTurn
Redefinir o rastreamento de dicas de gestos
O sistema rastreia o histórico de interação do usuário e mostra dicas de gestos flutuantes com base na configuração de cadência global (como Sempre ou Diariamente). Ao depurar os indicadores de gestos do app, redefina esse histórico de rastreamento para que as dicas apareçam novamente no seu pacote:
Em builds ou emuladores
userdebug:adb shell cmd IWearGestureService hint clear <your_package_name>Em builds de varejo (
user):Em dispositivos comerciais sem acesso root, o
hint clearé bloqueado pelas permissões do sistema. Limpe os dados locais do app para redefinir a descoberta de dicas:adb shell pm clear <your_package_name>
Restaurar restrições padrão
Para redefinir todas as substituições de restrição de depuração quando terminar o teste:
adb shell cmd IWearGestureService override-constraints reset
Resolver problemas de injeção de gestos
Se o app não receber gestos simulados:
Verifique se a tela do relógio está ativa e LIGADA. A estrutura de gestos não envia gestos para aplicativos enquanto a tela está desligada ou no modo ambiente. Para ativar a tela usando o ADB, execute:
adb shell input keyevent KEYCODE_WAKEUPVerifique se o app está registrado como um assinante de gestos ativo e se tem o foco da janela:
adb shell cmd IWearGestureService get-active-gestures -readableQuando a tela de gestos do app está em primeiro plano e a tela está ativada, esse comando retorna
[DoublePinch]ou[DoublePinch, WristTurn]. Se uma lista vazia ([]) for retornada, verifique se a janela está em foco ou se as restrições fora do corpo estão bloqueando a ativação.Inspecione o estado do serviço de gestos interno e os tokens de assinante ativos:
adb shell dumpsys IWearGestureService
Outros recursos
Para orientações de design sobre quando e onde usar gestos com uma mão, consulte Gestos com uma mão.
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Guia de design de gestos com uma mão