回應焦點

提供視覺提示,簡化聚焦的視覺化效果

雖然 Material Design 主題中的所有可聚焦元素都已有與主題相符的焦點樣式,但您可能需要加入一些視覺元素,才能更容易找出聚焦的元素。很好的解決方案是將元素的邊框換成背景顏色,與背景形成鮮明對比:

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. 首先,在 UI 中建立以視覺化方式繪製所需提示的 IndicationInstance
    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 = { }
            )
    ) {}

瞭解焦點狀態

一般來說,每次聚焦狀態變更時,都會觸發 FocusEvent,而 focusable() 修飾符的父項則可使用 onFocusChanged() 修飾符監聽。

如果您需要瞭解焦點的狀態,可以將下列 API 與 onFocusChanged 修飾符搭配使用:

  • 如果聚焦於附加修飾符的可組合項,isFocused 會傳回 true
  • hasFocus 的運作方式與 isFocused 類似,但有很大的差異:它會檢查元素或子項的子項是否聚焦,而不是只查看當前
  • 只要按住焦點,isCaptured 就會傳回 true。舉例來說,如果 TextField 含有不正確的資料,就會發生這種情況,因此嘗試聚焦其他元素並不會清除焦點。

這些欄位如下所示:

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