Reagir ao foco

Forneça indicações visuais para facilitar a visualização do foco

Embora todos os elementos focalizáveis do tema do Material Design já tenham um estilo de foco que corresponde ao tema, pode ser necessário adicionar alguns elementos visuais para facilitar a detecção do elemento em foco. Uma boa solução seria mudar a borda do elemento com uma cor que tenha um bom contraste em relação ao plano de fundo:

var color by remember { mutableStateOf(Color.White) }
Card(
    modifier = Modifier
        .onFocusChanged {
            color = if (it.isFocused) Red else White
        }
        .border(5.dp, color)
) {}

Nesse exemplo, remember é usado para armazenar a cor da borda nas recomposições, e o contorno do elemento é atualizado sempre que o elemento ganha ou perde o foco.

Implementar indicações visuais avançadas

Com o Jetpack Compose, você também pode criar indicações visuais mais sofisticadas e avançadas que combinam melhor com sua interface.

  1. Primeiro, crie um IndicationInstance que desenhe visualmente o sinal desejado na sua IU:
    private class MyHighlightIndicationInstance(isEnabledState: State<Boolean>) :
        IndicationInstance {
        private val isEnabled by isEnabledState
        override fun ContentDrawScope.drawIndication() {
            drawContent()
            if (isEnabled) {
                drawRect(size = size, color = Color.White, alpha = 0.2f)
            }
        }
    }
  2. Em seguida, crie uma Indication e lembre-se do estado em foco:
    class MyHighlightIndication : Indication {
        @Composable
        override fun rememberUpdatedInstance(interactionSource: InteractionSource):
            IndicationInstance {
            val isFocusedState = interactionSource.collectIsFocusedAsState()
            return remember(interactionSource) {
                MyHighlightIndicationInstance(isEnabledState = isFocusedState)
            }
        }
    }
  3. Adicione Indication e InteractionSource à interface usando o modificador indication():
    val highlightIndication = remember { MyHighlightIndication() }
    var interactionSource = remember { MutableInteractionSource() }
    
    Card(
        modifier = Modifier
            .clickable(
                interactionSource = interactionSource,
                indication = highlightIndication,
                enabled = true,
                onClick = { }
            )
    ) {}

Entender o estado do foco

Geralmente, sempre que um estado do foco muda, uma FocusEvent é acionada na árvore, e os pais de um modificador focusable() podem ouvi-la usando o modificador onFocusChanged().

Se você precisa saber o estado do foco,use estas APIs com o modificador onFocusChanged:

  • isFocused vai retornar true se o elemento combinável ao qual o modificador está anexado estiver focado
  • A hasFocus funciona de maneira semelhante à isFocused, mas com uma diferença significativa: em vez de verificar apenas a atual, ela confere se o elemento ou um dos filhos está focado
  • isCaptured retorna true sempre que o foco é mantido. Isso acontece, por exemplo, quando uma TextField contém dados incorretos, de modo que a tentativa de focar outros elementos não remova o foco.

Esses campos são mostrados abaixo:

Modifier.onFocusChanged {
    val isFocused = it.isFocused
    val hasFocus = it.hasFocus
    val isCaptured= it.isCaptured
}