React to focus

Provide visual cues for easier focus visualization

While all the focusable elements from Material Theme already have a focus style that matches the theme, you might need to add some visual elements to make the focused element easier to spot. A good solution would be to change the border of your element with a color that has a good contrast with the background:

varcolorbyremember{mutableStateOf(Color.White)}
Card(
modifier=Modifier
.onFocusChanged{
color=if(it.isFocused)RedelseWhite
}
.border(5.dp,color)
){}

In this example, remember is used to store the color of the border across recompositions, and the outline of the element is updated every time the element gains or loses focus.

Implement advanced visual cues

With Jetpack Compose, you can also create more sophisticated and advanced visual cues that match better with your UI.

  1. First, create an IndicationInstance that visually draws the cue you want in your UI:
    privateclassMyHighlightIndicationNode(privatevalinteractionSource:InteractionSource):
    Modifier.Node(),DrawModifierNode{
    privatevarisFocused=false
    overridefunonAttach(){
    coroutineScope.launch{
    varfocusCount=0
    interactionSource.interactions.collect{interaction->
    when(interaction){
    isFocusInteraction.Focus->focusCount++
    isFocusInteraction.Unfocus->focusCount--
    }
    valfocused=focusCount > 0
    if(isFocused!=focused){
    isFocused=focused
    invalidateDraw()
    }
    }
    }
    }
    overridefunContentDrawScope.draw(){
    drawContent()
    if(isFocused){
    drawRect(size=size,color=Color.White,alpha=0.2f)
    }
    }
    }
    
  2. Next, create an Indication and remember the focused state:
    objectMyHighlightIndication:IndicationNodeFactory{
    overridefuncreate(interactionSource:InteractionSource):DelegatableNode{
    returnMyHighlightIndicationNode(interactionSource)
    }
    overridefunhashCode():Int=-1
    overridefunequals(other:Any?)=other===this
    }
  3. Add both the Indication and an InteractionSource to the UI, via the indication() modifier:
    varinteractionSource=remember{MutableInteractionSource()}
    Card(
    modifier=Modifier
    .clickable(
    interactionSource=interactionSource,
    indication=MyHighlightIndication,
    enabled=true,
    onClick={}
    )
    ){
    Text("hello")
    }

Understand the state of the focus

Generally, every time a state of the focus changes, a FocusEvent is fired up the tree, and the parents of a focusable() modifier can listen to it using the onFocusChanged() modifier.

If you need to know the state of the focus,you can use these APIs in conjunction with the onFocusChanged modifier:

  • isFocused returns true if the composable to which the modifier is attached is focused
  • hasFocus works similarly to isFocused, but with a substantial difference: rather than checking only the current, it checks if the element or one of its children is focused
  • isCaptured returns true whenever the focus is held. This happens, for instance, when a TextField contains incorrect data, so that trying to focus other elements will not clear the focus.

These fields are shown below:

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

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Last updated 2026年07月21日 UTC.