포커스에 반응

포커스 시각화가 쉽도록 시각적 신호 제공

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. 먼저 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를 반환합니다.
  • hasFocusisFocused와 유사하게 작동하지만 상당한 차이가 있습니다. 현재 항목만 확인하는 대신 요소 또는 그 하위 요소 중 하나에 포커스가 있는지 확인합니다.
  • isCaptured는 포커스가 홀드될 때마다 true를 반환합니다. 예를 들어 TextField에 잘못된 데이터가 포함되어 있어 다른 요소에 포커스를 두려고 해도 포커스가 지워지지 않을 수 있습니다.

이러한 필드는 아래와 같습니다.

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