-
[Android] ViewTreeObserverAndroid 2021. 1. 3. 22:04
Background
회사에서 KeyboardHeight를 구해야 했다. 관련 방법을 여러 가지 서치 하다가 ViewTreeObserver라는 방식을 알게 되었다.추후에 키보드 높이 구하기 라는 포스팅을 따로 작성하고, 오늘은 VIewTreeBoserver에 대하여 알아보자.
What is ViewTreeObserver?
공식문서를 살펴보면 View Tree의 번경 사항을 알려주는 리스너를 등록해서 사용하면 된다고 나와있다.
필자는 이것을 Dialog RootView에서 사용하였는데, 예를 들어 Dialog가 만들어지고 editText에 포커스가 깜빡이고 키보드가 생길 때 키보드의 높이를 가져와서 padding인가 marging에 넣는 작업이었다.여기서 등록할수 있는 리스너 종류가 여러 가지가 있는데, 필자는 onGlobalLayoutListner를 사용하였다.
ViewTreeObserverListner종류
Listener Name Description ViewTreeObserver.OnDrawListener 뷰가 그려질때 ViewTreeObserver.OnGlobalFocusChangeListener 뷰 트리의 내의 포커스가 바꿔질때 ViewTreeObserver.OnGlobalLayoutListener 뷰 트리의 global layout 상태나 visibility 여부가 변경될때 ViewTreeObserver.OnPreDrawListener 뷰 트리가 그려지기 전 ViewTreeObserver.OnScrollChangedListener 뷰 트리 항목이 스크롤 되었을때 ViewTreeObserver.OnTouchModeChangeListener 터치 모드가 변경될 때 ViewTreeObserver.OnWindowAttachListener 뷰 트리가 window에 attach 되거나 detach될 때 ViewTreeObserver.OnWindowFocusChangeListener 뷰 트리의 window focus 상태가 변경 될 때 How to Use?
내가 rootView로 삼을 녀석에 addOnGlobalLayoutListenrer 을 등록하면 된다.
예를 들어 editText로 한다고 하면 아래와 같이 사용이 가능하다.
1.
editText.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { //whatever } })
2.
editText.viewTreeObserver.addOnGlobalLayoutListener{ //whatever }
3.
lateinit var listener : ViewTreeObserver.OnGlobalLayoutListener listener = object : ViewTreeObserver.OnGlobalLayoutListener{ override fun onGlobalLayout() { //whatever } } editText.viewTreeObserver.addOnGlobalLayoutListener(listener)
object로 listener 추가해서 오버라이드 하는 방식도 있고, 람다를 이용하는 방식도 있고, 전역 변수로 리스너 추가해서 사용하는 방식도 있다.
뭐 사용자의 용도에 알맞게 사용하면 되지 않을까 싶다. ~_~🔥 Attention 🔥
addOnGlobalLayoutListener 를 추가하고 나서 꼭 따라다니는 게 removeOnGlobalLayoutListener(ViewTreeObserver.OnGlobalLayoutListener victim)이다.
removeOnGlobalLayoutListener를 사용하는 이유는 memory leak을 방지하기 위해서이다.
외국 블로그에서 람다를 사용했기 때문에 객채에 대한 참조가 없고 람다와 객체는 정확히 같지 않아서 블라블라 어쩌고 하는데. removeOnGlobal를 해주는 게 확실히 메모리 관리에 좋음을 로그로 확인하였다.🙂1.
editText.viewTreeObserver.removeOnGlobalLayoutListener { }
2.
editText.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { editText.viewTreeObserver.removeOnGlobalLayoutListener(this) } })
3.
editText.viewTreeObserver.removeOnGlobalLayoutListener(listner)
위 addOnGlobalLayoutListenrer 순서에 맞게 remove 하는 것도 예시로 달아봤다.
잘못된 곳에 remove리스너를 등록하면 1회성 리스너로 인지 할 수 있기 때문에,
본인의 용도나 활용 방법에 따라서 야무지게 등록해줘야 하는 것 같다.
개인적으로 remove 하려면 listener가 victim으로 필요하기에 필자는 3번 방법이 좋았던 것 같다.Reference
* antonioleiva.com/kotlin-ongloballayoutlistener/
* faith-developer.tistory.com/188
* developer.android.com/reference/android/view/ViewTreeObserver
LIST'Android' 카테고리의 다른 글
[Android] fitSystemWindows (0) 2021.08.21 [Android] Android Context (0) 2020.10.04 [Android] RecyclerView DiffUtil (0) 2020.05.24 [Android] Android Stack 관리 / 확인하기 (0) 2020.02.16 [Android]FragmentLifeCycle (0) 2019.07.10