다메다메의 기술블로그

View의 위치, 사이즈(크기) 구하기 본문

Android

View의 위치, 사이즈(크기) 구하기

다메 2015. 1. 21. 10:25

 

Activity에서 배치한 콤포넌트(Layout이나 View들)위치나 사이즈를 구해야 할 경우가 있다.

 

이럴때는 어디서 구하면 될까?

단순히 "onCreate에서 구하면 구해지겠지"..라고 생각했었다.

onCreate에서 뷰의 사이즈를 구해보았다.


@Override

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main);

        View testView = (View) findViewById(R.id.test_view);

        Log.d("testView", "Width : " + testView.getWidht() );
        Log.d("testView", "Height : " + testView.getHeight() );

    }


결과


testView Width : 0

testView Height : 0


onCreate에서는 가로,세로 사이즈가 0으로 나왔다. 잘 생각해 보니 onCreate에서 xml 파일을 설정해 주었고 UI Thread에서 동작하는 onCreate에서 View의 생성이 완료 될 리가 없었다.


onResume에서 구해보자.

 

@Override
    protected void onResume() {

        super.onResume();

       
        View testView = (View) findViewById(R.id.test_view);


        Log.d("testView", "Width : " + testView.getWidht() );
        Log.d("testView", "Height : " + testView.getHeight() );

    }



결과


testView Width : 0

testView Height : 0


onResume에서도 가로,세로 사이즈가 0으로 나온다. onResume가 호출되는 시점에서도 구할 수가 없군..onResume에서 구할 수 없으니 당연히 onStart에서도 구할 수 없을테고..


그러면 onWindowFocusChanged에서 구해 볼까?

 

@Override
public void onWindowFocusChanged(boolean hasFocus) { 
        View layoutMainView = (View)this.findViewById(R.id.mainLayout);
        Log.w("Layout Width - ", String.valueOf(layoutMaintView.getWidht()));
        Log.w("Layout Height - ", String.valueOf(layoutMaintView.getHeight()));
}
 

 

결과


testView Width : 100

testView Height : 100

 

잘 구해진다. "해피해피하게 이 방법으로 View들의 사이즈를 구하면 되겠군" 라고 생각했다.

 

그러나 사용하다 보니 위의 함수는 말 이름 그대로 포커스가 변할 때마다 불렸다.

 

무슨 말이냐면 유저가 해당 Activity를 실행했을 때도 호출되고 해당 Activity를 종료 했을 때도 호출되고 다른 Activity로 이동했을 때에도 호출된다.

 

나의 경우 9개 정도의 View의 사이즈를 구해 높이와 폭을 -10 해주고 있었는데 이 처리를 Activity 종료시나 타 Activity로 이동할 시에도 매번 수행하는 것이었다.

 

Flag를 사용하면 금방 해결 될 문제지만 분명히 이 문제는 View가 다 그려진 타이밍에 불리는 콜백 함수가 있을듯했다. 검색하니 금방 나왔다...(OTL)

 

OnGlobalLayoutListener라는 리스너인데.. Global Layout의 상태나 ViewTree 상태가 변화했을때 불리는 리스너이다.

이 리스너를 사용하면 View가 전부 그려진 후 호출되므로 View의 크기를 구할수 있다


한가지 주의 할 점은 상태가 변하면 호출되기 때문에 View의 상태(사이즈등..)가 변하는 처리가 들어있을때는 여러번 호출되게 된다.


한번 View의 크기를 구한 후 다시 구할 필요가 없을 경우에는 이 리스너를 반드시 제거해주어야 한다


리스너 생성

mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {

            @Override

            public void onGlobalLayout() {


                int width = mParentLayout.getWidth();

                int height = mParentLayout.getHeight();

                Log.d(TAG, "width = " + width);

                Log.d(TAG, "height = " + height);


//리스너 제거를 위한 메소드

                removeOnGlobalLayoutListener(mParentLayout.getViewTreeObserver(), mGlobalLayoutListener);

            }

};


리스너 등록

mParentLayout.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);

 

리스너 삭제 메소드

private static void removeOnGlobalLayoutListener(ViewTreeObserver observer, ViewTreeObserver.OnGlobalLayoutListener listener) {

        if (observer == null) {

            return ;

        }

        

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {

            observer.removeGlobalOnLayoutListener(listener);

        } else {

            observer.removeOnGlobalLayoutListener(listener);

        }

    }


위와 같이 등록하여 View의 크기를 구한 후 리스너는 삭제 해 버리면 된다.


Comments