[Compose] Modifier Extension - AddFocusCleaner

이번 포스팅에서는 Jetpack Compose에서 포커스를 해제하는 동작을 손쉽게 추가할 수 있는 확장 함수 addFocusCleaner를 소개하고자 합니다.

 

addFocusCleaner 함수의 개요

addFocusCleaner 함수는 Modifier의 확장 함수로, 컴포저블에 포커스 해제 기능을 추가합니다.

 

이 함수는 다음과 같은 상황에서 유용합니다:

  • 사용자 입력이 끝난 후, 다른 영역을 탭했을 때 포커스를 해제하고 싶을 때
  • 포커스 해제 시 추가적인 동작을 실행하고자 할 때
fun Modifier.addFocusCleaner(
    focusManager: FocusManager, 
    doOnClear: () -> Unit = {}
): Modifier {
    return this.pointerInput(Unit) {
        detectTapGestures(onTap = {
            doOnClear()
            focusManager.clearFocus()
        })
    }
}

 

주요 파라미터

  • focusManager:
    현재 포커스된 컴포넌트의 포커스를 해제하는 데 사용되는 FocusManager.
    Jetpack Compose에서 포커스는 여러 컴포넌트 간에 공유되며, focusManager.clearFocus()를 호출하여 특정 컴포넌트에서 포커스를 해제할 수 있습니다.
  • doOnClear:
    포커스 해제 시 실행되는 선택적인 람다 함수.
    기본적으로 빈 함수이지만, 필요에 따라 포커스를 해제할 때 추가적인 동작을 정의할 수 있습니다.

 

동작 원리

addFocusCleaner는 Modifier에 pointerInput을 사용하여 탭 제스처 감지기를 추가합니다.
사용자가 컴포저블을 탭할 때, onTap 콜백이 실행되어 doOnClear 람다 함수가 호출된 후 focusManager.clearFocus()를 통해 포커스가 해제됩니다.

 

활용 예시

@Composable
fun MyTextField(focusManager: FocusManager) {
    var text by remember { mutableStateOf("") }

    TextField(
        value = text,
        onValueChange = { text = it },
        modifier = Modifier
            .fillMaxWidth()
            .addFocusCleaner(focusManager) {
                // 포커스 해제 시 추가적인 동작을 정의
                Log.d("FocusCleaner", "포커스가 해제되었습니다.")
            }
    )
}

위 코드에서, MyTextField는 텍스트 입력을 위한 간단한 UI 컴포넌트입니다.

addFocusCleaner 확장 함수가 적용되어, 사용자가 입력 필드 외부를 탭하면 포커스가 해제되고 로그 메시지가 출력됩니다.

 

addFocusCleaner의 장점

  1. 코드 간결화: 여러 컴포저블에서 반복되는 포커스 해제 로직을 추상화하여 코드 재사용성을 높입니다.
  2. 유연성: doOnClear 파라미터를 통해 포커스 해제 시 추가적인 동작을 쉽게 정의할 수 있습니다.
  3. 확장 가능성: pointerInput과 detectTapGestures를 이용하여 다양한 입력 제스처에도 확장할 수 있습니다.

 

확장 및 개선 아이디어

addFocusCleaner는 매우 기본적인 동작만을 정의하지만, 이를 바탕으로 더 복잡한 포커스 관리 로직을 추가할 수 있습니다. 예를 들어, 특정 조건에 따라 포커스를 해제할지 여부를 결정하거나, 포커스를 해제할 때 애니메이션을 적용하는 등의 확장 가능성이 존재합니다.

fun Modifier.addConditionalFocusCleaner(
    focusManager: FocusManager, 
    condition: () -> Boolean,
    doOnClear: () -> Unit = {}
): Modifier {
    return this.pointerInput(Unit) {
        detectTapGestures(onTap = {
            if (condition()) {
                doOnClear()
                focusManager.clearFocus()
            }
        })
    }
}

위의 addConditionalFocusCleaner는 포커스 해제를 위한 조건을 추가하여, 사용자가 정의한 조건에 따라 포커스 해제가 수행됩니다. 이를 통해 상황에 맞는 포커스 관리를 보다 유연하게 적용할 수 있습니다.

 

'[Android - Compose] > Compose Modifier' 카테고리의 다른 글

[Compose] Modifier Extension - DrawScrollbar  (0) 2024.09.25