TextField, OutlinedTextField 를 사용한다면 사용하는 Material(2 or 3) 의 버전을, BasicTextField 라면 Compose Foundation 버전을 upgrade/downgrade 해보자.
TextField 의 키보드가 내려갔을 경우, focus 를 강제로 제거(clear)하는 방법으로도 해결할 수 도 있다.
https://github.com/Project-Unifest/unifest-android/issues/55
위의 이슈에 대해서 다뤄보려고 한다.
사실 이 이슈는 대략 1년이 넘은 시간 동안 날 괴롭혔던 이슈이다.
개인 사이드 프로젝트를 할때도, 기업 과제를 할 때도, 종종 발생했던 이슈이다.
물론 나만 겪었던 문제는 아니었다. 구글링을 통해 해당 문제를 검색해보면 많은 분들이 고통을 받고 있었다는 것을 알 수 있는데,
Clicking on TextField while it has focus does not show keyboard in jetpack compose Android
TextField not focusing and not showing keyboard in Compose 1.4.0 in DialogFragment with ComposeView
Keyboard is not shown when text field is in focus
TextField hide keyboard then tap again, keyboard does NOT show up any more
Jetpack Compose OutlinedTextField gets focus but, no keyboard show up
Jetpack Compose OutlinedTextView not opening keyboard after back press
...etc
글을 쓰면서 잠시 찾아봤는데 다음과 같이 관련된 StackOverflow 의 질문글과 이슈가 한 트럭(?)인 것을 볼 수 있다.
문제를 다시 한번 간단히 정리하면 다음과 같다.
1. TextField 를 터치(클릭)한다.
2. 키보드가 올라온다.
3. 키보드로 입력을 마친 후, 키보드 하단에 뒤로가기 버튼을 누르거나, done 버튼을 누른다.
4. 키보드가 내려간다.
5. TextField의 focus가 그대로 유지된다.(커서가 깜빡깜빡)
6. 다시 TextField 를 터치 (클릭) 한다.
7. 키보드가 올라오지 않는다...!
위의 질문 글들의 해답을 참고하면 공통점인 2가지의 해결법이 존재하는 것을 확인할 수 있다.
1. Compose 라이브러리 버전 upgrade/downgrade
2. 키보드가 내려갔을 때, TextField 의 focus 를 제거(clear)해준다.
먼저 1번 부터 보면,
Material3 라이브러리 버전을 downgrade 를 할 경우에 잘 동작한다는 답변이 가장 많았다.
또는 가장 최신 버전에선 해당 문제를 해결하였다는 답변도 존재하였다.
그동안 프로젝트에서 OutlinedTextField 를 다룰때마다, 코드를 동일하게 구현해도, 언제는 잘되고, 언제는 위의 문제가 발생하는 케이스가 존재하였는데, 아마 당시 프로젝트의 Materia3 버전에 따라, 문제 발생 여부가 결정되었을 것으로 추측된다.
Compose 의 컴포넌트 중에 Material3 ModalBottomSheet가 버그가 많기로 유명하였는데, 이에 대응하기 위해 Material3 의 버전은 compose-bom 의 버전을 따르지 않고, 별도로 지정해주는 일이 많았다. 그것의 Side Effect 였지 않나 싶다.
그 밖에 compose 자체 라이브러리 버전, compose-ui 라이브러리의 버전을 upgrade/downgrade 하라는 답변도 존재하였다. 많은 라이브러리들이 얽혀있어, 다양한 원인이 존재하는 문제같다.
다음으로 2번이다.
이는 내 경험상, 완전한 해결책은 아니었다. 왜냐하면 언제는 문제가 해결되었고, 언제는 적용해도 문제가 여전히 발생했기 때문이다.
여러 답변에서 custom 으로 제작한 Modifier 를 제공해주는 것을 확인할 수 있었는데, 공통의 목적은 키보드가 내려갔을 경우, TextField 의 focus 자체를 제거하는 것이다.(커서가 깜빡거리지 않도록)
그러면 다음에 다시 TextField 를 터치(클릭)할 경우 focus가 잡히면서, 키보드가 정상적으로 올라온게 된다.
이는 해당 문제를 해결하려는 요구 뿐만 아니라, 키보드가 내려가면 focus를 제거하는 동작을 원하는 사람들도 존재하기에, 라이브러리로도 존재하는 것을 확인할 수 있었다.
https://github.com/taehwandev/ComposeExtensions
다음과 같이, 동일한 Scaffold 내에 화면들에서 키보드가 내려갔을 경우에 대한 포커스를 제거하는 Modifier 와 keyboard 가 현재 열려있는지, 닫혀있는지에 대한 state 를 제공한다.
해당 라이브러리를 최근까지 잘 사용해왔으나, 동일한 Scaffold 위에 있는 화면이 아니라, 별도의 Activity 내에 화면, ModalBottomSheet 내에 존재하는 TextField 의 경우에는 간단하게 문제가 해결되지 않았다...
난 1번을 통해 해결하는 것이 정답이라 생각하여, 1번으로 문제를 해결하였고, 2번의 동작(키보드가 내려가면 TextField focus 제거)을 원하기 때문에 2번도 사용하고 있다.
원래 버전이 잘 맞는다면, focus 가 유지되든 말든 다시 키보드는 잘 올라올 것이기에, focus를 제거하는게 완벽한 해결법이 아니라고 말한 것도 있다.
이번엔 평소와 다른 라이브러리의 버전을 수정하여서, 문제를 해결하였는데,
Keyboard is not reopened when clicking on TextField in Foundation 1.6.0-beta01
참고한 글은 위와 같다.
왜냐하면 처음으로 BasicTextField2 를 사용해봤기 때문이다.
위 글의 답변을 요약하자면 BasicTextField2 는 이제 아직 Stable 한 버전이 아니기에 compose-foundation 라이브러리의 버전을 compose-bom 의 버전이 아닌 (글을 쓰는 시점에선 1.6.5 버전) 1.7.0-alpha01 버전 이상으로 설정해야 한다는 것이었다.
당연하다고 생각할 수 있는게, BasicTextField 는 Material의 것이 아닌 compose-foundation 에 속하기 때문에 버전의 문제라면 foundation 쪽을 의심하는 것이 타당했다.
따라서 글을 작성하는 시점에서 가장 최신 버전인 1.7.0-alpha06 버전으로 upgrade를 하였고, 정상적으로 focus가 제거가 되던, 말던 다시 키보드가 올라오는 것을 확인할 수 있었다.(Modal BottomSheet 내에 Textfield 도!)
끝!
하지만, 현재 앱에서 사용하고 있는 중요한 달력 라이브러리가 아직, compose 1.7 버전 이상을 지원하지 않기에, 1.7 버전 이상으로 올리면 앱이 죽는 문제가 발생하였다.
BasicTextField2 써보자고, 앱의 주요한 기능인 달력을 포기할 순 없었기에, 눈물을 머금고 BasicTextField 로 migration 해주었다. 다음에 제대로 써보는걸로 흑흑
BasicTextField 의 경우엔 1.7 버전으로 올리지 않아도, compose-bom 버전(1.6.5)에서도 정상적으로 동작하는 것을 확인할 수 있었다.
이런게 써드파티 라이브러리에 너무 의존도가 높을 경우 발생할 수 있는 문제인 것 같다. 편하자고 다 가져다 쓰다가도, 한번씩은 경계하는 태도를 가져봐야겠다.
최신 버전의 compose-foundation 가 몇 버전인지 확인을 위해 공식문서에서, 버전 별 변경사항을 확인하면서 든 생각은
이 놈들 정말 많이 만들었다가, 지워버린다는 것이었다.
이래서 alpha 버전을 쓰지 말라는거구나 싶었다. 달력 라이브러리가 1.7.x 버전을 아직 지원안하는게 어찌보면 당연하다고 생각이 들었다. 대응해봤자 바뀌어버리면, 다시 대응해줘야 하기 때문이다.
1.7.0-alpha04 버전에서
https://developer.android.com/jetpack/androidx/releases/compose-foundation
다음과 같은 소식을 접할 수 있었는데, BasicTextField2가 BasicTextField 로 다시 돌아갔다는 내용이다.
개발자들이 Paging2 와 Paging3 처럼, 기존의 BasicTextField 와 아예 분리된, 새로운 컴포넌트를 만들려고 했는데, 기존의 버전을 보완한 업데이트 버전 정도로 만드는 것으로 계획을 변경한 것 같다.
1.7.0-alpha06 버전에선, 이전 글에서 언급했던, 편리해보였던 확장함수도 제거해버린 것을 확인할 수 있었다. 이럴꺼면 왜 만들었는지... 만드는 본인들이 제일 아쉽겠지만, 아직 문제가 많은가보다. 그동안에도 문제 많았는데, 적어도 beta 버전이 나올 때까진 기다려봐야겠다.