오늘도 삽질중

Android Compose TextField 를 쓰다가 네이티브로 변경한 이유 본문

안드로이드

Android Compose TextField 를 쓰다가 네이티브로 변경한 이유

Choi3950 2021. 12. 29. 23:34
반응형

글을 쓰는 현재 시점  Compose 1.0.5 를 쓰고 있습니다.

해당 문제는 버전이 올라가면 자연스럽게 해결되는 이슈라 생각합니다.

 

현재 개발중인 프로젝트에 비교적 단순한 Ui의 경우 Compose 로 구현 및 개발을 진행하고 있습니다.

금일 작업하면서 겪었던 이슈를 공유하고자 합니다.

제가 무언가를 빠트렸거나 실수했다면 댓글로 지적 부탁드립니다.

 

참고로 오늘 작업한 화면의 핵심 기능은

하나의 EditText에 닉네임을 입력하고 버튼을 눌러 수정하는 비교적 정말 간단한 화면입니다.

 

기존 안드로이드 네이티브에서 쓰이는 EditText 를 Compose 에서는 TextField 로 제공하고 있습니다.

자...제가 작업하면서 발생한 이슈는 크게 3가지 입니다.

 

 

1. Text Field 옵션 중 maxLength 를 제공해주지 않는다.

 

2. 키보드가 올라간 상황에서 백버튼을 세 번 눌러야 이전 화면으로 돌아간다.

 

3. 1번의 이슈를 해결하려고 소스를 참고하고 테스트하니 입력한 값이 사라진다

 

 

1번의 경우는 설마설마 했습니다. 하지만 정말로 maxLength를 제공해 주지 않았습니다.

뭐 여기까진 이해합니다. 그래서 구글링을 열심히 해서 적용을 해봤더니

이해할수 없는 상황이 발생했습니다.

 

var text by remember { mutableStateOf(TextFieldValue("")) }
val maxChar = 5

TextField(
    singleLine = true,
    value = text,
    onValueChange = {
        if (it.length <= maxChar) text = it         
    }
)

스택오버 플로우에 있는 소스입니다.

maxChar 로 최대 자릿수를 정한 뒤, onValueChange 에서 값을 비교하여 작거나 같을 경우에만 데이터를 세팅합니다.

이렇게 적용을 하니 위의 세가지 중 3번째 문제가 발생합니다.

 

최대 값으로 정한 5개까지는 텍스트 필드에 정상적으로 쌓이다가 6번째 이상 키보드를 누르면 텍스트 필드가 초기화됩니다.

로그를 찍어봐도 데이터가 없습니다.

 

 

 

2번째 이슈는 키보드가 올라간 상황에서 이전화면으로 돌아가려면 백버튼을 세 번 눌러야 됩니다.

흔히 앱을 쓰다보면 

키보드가 올라간 상태 -> 뒤로가기를 누름 -> 키보드가 닫힘 -> 뒤로가기를 누름 -> 이전화면으로 이동

 

이런 흐름을 많이 보셨을텐데

컴포즈의 텍스트 필드는 이렇게 동작합니다.

 

키보드가 올라간 상태 -> 뒤로가기를 누름 -> 키보드가 닫힘 -> 뒤로가기를 누름 -> 텍스트 필드에 잡힌 포커스가 해제 됨

-> 뒤로가기를 누름 -> 이전화면으로 이동

 

 

우리가 익숙했던 뒤로가는 프로세스에서 한번 더 동작이 추가됩니다.

즉 사용성이 불편해진다고 생각이 듭니다.

 

onBackPressed() 를 오버라이딩 해서 직접 포커스도 제거해보고 해봤는데 매끄럽게 되지 않습니다.

그나마 다행인건 해당 문제는 해결이 가능합니다.

 

    def compose_inset_version = "0.22.0-rc"
    implementation "com.google.accompanist:accompanist-insets:$compose_inset_version"
    implementation "com.google.accompanist:accompanist-insets-ui:$compose_inset_version"

그래들에 compose insert 을 임포트 후

 

fun Modifier.clearFocusOnKeyboardDismiss(): Modifier = composed {
    var isFocused by remember { mutableStateOf(false) }
    var keyboardAppearedSinceLastFocused by remember { mutableStateOf(false) }
    if (isFocused) {
        val imeIsVisible = LocalWindowInsets.current.ime.isVisible
        val focusManager = LocalFocusManager.current
        LaunchedEffect(imeIsVisible) {
            if (imeIsVisible) {
                keyboardAppearedSinceLastFocused = true
            } else if (keyboardAppearedSinceLastFocused) {
                focusManager.clearFocus()
            }
        }
    }
    onFocusEvent {
        if (isFocused != it.isFocused) {
            isFocused = it.isFocused
            if (isFocused) {
                keyboardAppearedSinceLastFocused = false
            }
        }
    }
}

Compose Modifier 확장함수를 선언합니다.

그 이후에 텍스트 필드에 추가해주면 됩니다.

 

BasicTextField(
    value = valueState.value,
    onValueChange = {
        valueState.value = it
    },
    modifier = Modifier
        .clearFocusOnKeyboardDismiss()
)

직접 테스트해보니 키보드가 올라간 상황에서 두번의 뒤로가기 버튼으로 이전화면 이동이 가능합니다.

다만 기본 네이티브 EditText 에서는 겪지 않았는 문제를 해결 하기 위해 참 번거롭다는 생각이 듭니다.

 

해당 해결방법이 기재된 링크입니다.

https://stackoverflow.com/questions/68389802/how-to-clear-textfield-focus-when-closing-the-keyboard-and-prevent-two-back-pres

 

How to clear TextField focus when closing the keyboard and prevent two back presses needed to exit app in Jetpack Compose?

I'm using BasicTextField. When I start editing, back button becomes hide keyboard button(arrow down). First press on back button hides keyboard, but the focus is still on the text field. Both

stackoverflow.com

 

 

우선 저는 maxLength 옵션이 필요했기 때문에 다시 네이티브로 전환을 했습니다.

정말...maxLength 가 없는건 상상도 못했네요.

참고로 Compose Text 는 includefontPadding 옵션도 제공해주지 않아 커스텀 폰트를 쓸 경우

기본 패딩이 늘어나 있는 이슈도 있던데...

 

물론 Compose를 직접 써보니 좋은점도 많고 편하긴 한데 디테일한 부분을 충족하기엔

아직까진 부족한 부분이 많은거 같습니다.

 

 

금일 제가 겪었던 이슈 해결방법을 아시거나,

제가 잘못해서 이슈가 발생했다면 조언 및 지적 환영합니다.

 

 

 

반응형
Comments