• Flutter app에서 TextField 등의 widget을 탭하면 해당 widget의 FocusNode가 활성화되면서 가상 키보드가 나타남
  • 가상 키보드를 닫으려면 해당 widget의 FocusNode를 비활성화(unfocus) 시켜야 한다.

FocusScope 사용

  • FocusScopeFocusNode를 하나의 group으로 묶어서 관리할 때 사용하는 widget으로, Route가 push될 때 자동으로 생성되어 widget tree에 추가됨
  • FocusScope.of(context) method가 반환하는 FocusScopeNodeFocusNode의 subclass로, FocusScope group 안에서 focus를 제어하는 객체
  • FocusScopeNodeunfocus()를 호출해서 현재 focusing된 widget(e.g. TextField)을 unfocus 시킨다.
    FocusScope.of(context).unfocus();
    
  • 또는, requestFocus()에 새로운 FocusNode를 전달하여 이전 focus를 해제시킨다.
    FocusScope.of(context).requestFocus(FocusNode());
    

FocusManager 사용

  • FocusManager는 app의 전체 focus tree를 관리하는 전역 객체로 모든 FocusNodeFocusScope를 관리함
  • FocusManager.instance.primaryFocus로 현재 focus가 활성화된 FocusNode를 반환함
  • FocusNodeunfocus()를 호출해서 unfocus 시킨다.
    FocusManager.instance.currentFocus?.unfocus();
    

FocusScopeFocusManager 중 어떤 것을 사용할까?

  • FocusScopeFocusManager는 각자 수행하는 역할이 다르다.
    • FocusScopeFocusNode를 group으로 묶어서 관리할 때 사용한다.
    • FocusManager는 app 전역에서 focus를 제어하거나 focus 흐름을 추적할 때 사용한다.
  • App에서 화면 빈 곳 등을 터치해서 가상 키보드를 닫으려고 할 때는 어떤 것을 사용해도 크게 문제되지 않는다.
  • 단, FocusScope.of(context) code에 의해 현재 widget에서 focus가 변경될 때 마다 widget을 rebuild 하여 성능 문제가 발생할 여지가 있다.
  • FocusManager는 전역 객체이므로, 일반적인 상황에서는 현재 widget으로부터 가장 가까운 local 객체인 FocusScope를 사용하고 불필요한 widget rebuild에 의한 성능 문제가 발생한다면 FocusManager를 사용하는게 좋을 것 같다.

Reference