티스토리 뷰





ViewTreeObserve


뷰의 위치(높이,  넓이) 구하기, 레이아웃 그려지는 시점 알아내기

# 뷰가 그려지지 않을때 혹은 / 뷰의 높이가 0일때 참고


   ViewTreeObserve 란


ViewTreeObserve - http://developer.android.com/intl/ko/reference/android/view/ViewTreeObserver.html


뷰 트리 관찰자가 View 트리에서 글로벌 변경 알림을 받을 수 있는 리스너를 등록 하는데 사용 된다.

이름에서 알 수 있듯 뷰트리에 대한 옵저버 역할을 하게 된다. 

View가 생성되기 전에 View의 위치나 크기를 구하려고 하면 아직 View의 위치가 실제로 화면에 변경되기 전에 값을 가져오므로 0이나 Null값을 가져오게 될것이다.

그래서 ViewTreeObserve를 이용하여 리스너를 등록하고 리스너를 통해 뷰의 크기나 위치를 가져오는 시점으로 사용하면 값을 가져올 수 있다.




   ViewTreeObserve 가져오기 getViewTreeObserve


getViewTreeObserve  - http://developer.android.com/intl/ko/reference/android/view/View.html#getViewTreeObserver()

최상위 클래스인 View 클래스에서 getViewTreeObserve()를 통하여 ViewTreeObserve를 가져온다.

imageView = (ImageView)findViewById(R.id.bitmap);
ViewTreeObserver viewTreeObserver = imageView.getViewTreeObserver();

가져온 ViewTreeObserve에 3가지 리스너를 등록시킬 수 있다.



   ViewTreeObserve 리스너 등록


ViewTreeObserve는 ViewTree의 높이를 구하기 좋은 2가지의 상태에 대해 리스너를 추가 시킬 수 있다.

addOnGlobalFocusChangeListener

addOnGlobalLayoutListener


위와 같이 리스너를 등록하고 지속적인 프레임의 변화를 감지하는 작업이 아닌 뷰가 생성되고 한번정도 값을 가져오는 작업이라면

반드시 리스너를 리무브 해줘 호출을 받아오지 않도록 한다.


// ViewTree의 포커스 변경이 있을 경우
imageView.getViewTreeObserver()
.addOnGlobalFocusChangeListener(new ViewTreeObserver.OnGlobalFocusChangeListener() {
@Override
public void onGlobalFocusChanged(View oldFocus, View newFocus) {

//필요한 작업

//리스너 해제
imageView.getViewTreeObserver().removeOnGlobalFocusChangeListener(this);
}
});

// ViewTree의 뷰가 그려질 때마다
imageView.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {

//뷰의 생성된 후 크기와 위치 구하기
imageView.getWidth();
imageView.getHeight();
imageView.getX();
imageView.getY();


//리스너 해제
imageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});




   ViewTreeObserve의 유용한 리스너


interface ViewTreeObserver.OnDrawListener 뷰를 그릴
interface ViewTreeObserver.OnGlobalFocusChangeListener 전체 뷰의 포커스가 바뀔
interface ViewTreeObserver.OnGlobalLayoutListener 전체 뷰가 그려질 때
interface ViewTreeObserver.OnPreDrawListener 뷰가 그려지기 전
interface ViewTreeObserver.OnScrollChangedListener 스크로 상태의 변경시
interface ViewTreeObserver.OnTouchModeChangeListener 터치 모드 변경시
interface ViewTreeObserver.OnWindowAttachListener 뷰의 계층구조에 붙을 때와 떨어져 나갈때
interface ViewTreeObserver.OnWindowFocusChangeListener 윈도우 포커스 변경시


댓글
  • 프로필사진 1465977448 알찬 정보 좋네요~ 2016.06.15 16:57
  • 프로필사진 eorjs onDrawlistener와 onGlobalLayoutListener의 차이가 뭔가요?
    서로 다른 시점에 호출되던데요. 차이점을 알고 싶습니다.
    또한 onDrawListener의 경우 해제를 어떻게 해야 하나요? onGlobalLayoutListner이 경우 내부에서 해제가 가능하지만
    onDrawListener도 동일하게 해제하도록 했더니 exception이 발생하며 앱이 죽습니다.
    2018.08.06 16:30
  • 프로필사진 DWFOX DWFOX 안드로이드 개발자 사이트에서 onDrawlistener 는 ViewTree들이 그려질때 호출되는 시점의 리스너이고 onGlobalLayoutListner는 그려지기전 뷰의 가시성이 변경될때 호출되는 리스너라고 설명되어 있습니다.

    그래서 onDrawlistener가 호출되기전 onGlobalLayoutListner이 호출되어 질것으로 생각됩니다.

    exception은 정확한 메세지가 있으면 확인할 해볼 수 있을것 같습니다.
    2018.08.07 15:41 신고
  • 프로필사진 eorjs 답변 감사합니다.

    안드로이드 개발자 사이트에서 onDrawListener의 설명 중 아래 내용이 있습니다.
    An ViewTreeObserver.OnDrawListener listener cannot be added or removed from this method.

    onDrawListener의 onDraw 안에서 해제가 불가능하다는 것으로 이해했습니다.
    실제로 발생한 exception도 같은 내용이었습니다.
    2018.08.07 16:20
댓글쓰기 폼