响应焦点

提供视觉线索以方便聚焦可视化

虽然 Material Theme 中所有可聚焦元素都具有与主题匹配的焦点样式,但您可能需要添加一些视觉元素来使聚焦元素更容易被发现。一个好的解决方案是使用与背景形成良好对比的颜色更改元素的边框。

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

在本例中,remember 用于在重新组合过程中存储边框的颜色,并且每次元素获得或失去焦点时都会更新元素的轮廓。

实现高级视觉线索

使用 Jetpack Compose,您还可以创建更复杂和高级的视觉线索,使其更符合您的 UI。

  1. 首先,创建一个IndicationInstance,在您的 UI 中以视觉方式绘制您想要的线索
    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. 接下来,创建一个Indication 并记住聚焦状态
    class MyHighlightIndication : Indication {
        @Composable
        override fun rememberUpdatedInstance(interactionSource: InteractionSource):
            IndicationInstance {
            val isFocusedState = interactionSource.collectIsFocusedAsState()
            return remember(interactionSource) {
                MyHighlightIndicationInstance(isEnabledState = isFocusedState)
            }
        }
    }
  3. 通过indication() 修饰符将IndicationInteractionSource 都添加到 UI 中
    val highlightIndication = remember { MyHighlightIndication() }
    var interactionSource = remember { MutableInteractionSource() }
    
    Card(
        modifier = Modifier
            .clickable(
                interactionSource = interactionSource,
                indication = highlightIndication,
                enabled = true,
                onClick = { }
            )
    ) {}

了解焦点的状态

通常,每次焦点的状态发生变化时,都会向上触发一个FocusEventfocusable() 修饰符的父级可以使用onFocusChanged() 修饰符监听它。

如果您需要知道焦点的状态,您可以将这些 API 与onFocusChanged 修饰符结合使用

  • isFocused 如果附加修饰符的可组合项处于焦点状态,则返回true
  • hasFocus 的工作方式类似于isFocused,但存在一个重大差异:它不仅检查当前状态,还检查元素或其子元素是否处于焦点状态。
  • isCaptured 每当焦点被保持时返回true。例如,当TextField 包含不正确的数据时,就会发生这种情况,因此尝试聚焦其他元素将不会清除焦点。

这些字段如下所示

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