개발/Android

[Jetpack Compose] BasicTextField - clearFocus() 이슈

귀염둥이 팡무 2022. 7. 11. 02:03

Error Log

layoutcoordinate operations are only valid when isattached is true

시나리오

  1. BasicTextField 생성
  2. decorationBox안에 value(입력 값)이 empty이 아니면 innerTextField를 호출하지 않도록 함
  3. 키보드 엔터 누른 경우 search를 하고 키보드 숨김 및 focusManager로 clearFocus 호출
  4. 이때 text가 비어있는 상태에서 키보드 숨김 및 focus 해제 후 다시 BasicTextField를 클릭하면
  5. 앱 사망

분석

  1. clearFocus() 함수의 문제인가?
    1. clearFocus() 함수를 호출하고 이후 호출을 하지 않더라도 앱이 사망
  2. 키보드가 내려간 상태에서 textField를 클릭하였기 때문에 오류가 난건가?
    1. 키보드 관련 로직을 지우더라도 재현됨
  3. 구글링 해보니 Compose 자체 이슈라는 글들이 보임
    (다른 기능 구현 중 발생한 이슈들이지만 컴포즈 xxx에서 해결되었다함)
    1. Compose 1.2.0-alpha02 / Kotlin 1.6.10 업데이트하고 다시 해보았지만 사망
  4. 도대체 무엇이 문제인가…?

해결

  1. 혹시나 하는 마음에 decorationBox에 innerTextField를 반드시 반환 되도록 수정
  2. 잘 작동됨

원인 추측

  1. Material 디자인을 채택하지 않는 경우에는 BasicTextField를 사용해야함
  2. 특히 Hint 등 유연하게 디자인을 하기 위해서는 deocrationBox를 사용함
    1. decorationBox안에서 특정한 디자인 후 innerTextField()를 호출하면 텍스트 필드가 생성됨
  3. 이때 value(입력 값)이 empty가 아닌 경우에만 innerTextField()를 호출하도록 설정되었음
  4. value가 empty이었기에 innerTextField()가 호출되지 않았고, 이 상태에서 clearFocus()가 호출되면서 해당 BasicTextField는 focus가 해제됨
  5. 이 상태에서 BasicTextField를 클릭함으로써 focus를 주려고 하였지만, innerTextField가 없었기에 focus 대상을 찾지 못함
  6. 그로 인해 사망

결론

  • 아래의 3가지 조건 중 하나를 사용해야함
  1. BasicTextField에서 decroationBox 사용 시 innerTextField()는 반드시 존재해야함
  2. 반드시 입력 창이 존재하지 않아야 한다면, innerTextField 부모로 Modifier.size(0)을 두는 꼼수를 사용해야할 듯.
    1. (태환님 제보) 1.4.0-alpha04 부터는 size가 0.dp 인 경우 Exception이 발생하므로 최소 1.dp를 주어야 합니다.
  3. 또는 decorationBox에서 분기하는 것이 아닌, BasicTextField 자체를 보여줄지 말지 분기 필요

최초 작성일: 2022. 02. 17