Android中获取View的宽/高的时机

实际上在onCreate、onStart、onResume中均无法正确得到某个View的宽/高信息,这是因为View的measure过程和Activity的生命周期方法不是同步执行的。如果View还没测量完毕,那么获得宽/高就是0。下面列出获得View宽/高的机时:

 

Activity/View#onWindowFocusChanged

onWindowFocusChanged这个方法的含义是:View已经初始化完毕了,宽/高已经准备好。需注意的是,它会被调用多次,当Actitvity的窗口得到焦点和失去焦点时均会被调用一次。具体来说,当Activity继续执行和暂停执行时均会调用,如果频繁地进行onResume和onPause,那么它也会被频繁调用。典型代码如下:

@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
    super.onWindowFocusChanged(hasWindowFocus);
    if (hasWindowFocus) {
        int width = view.getMeasuredWidth();
        int height = view.getMeasuredHeight();
    }
}

 

view.post(rennable)

通过post可以将一个runnable投递到消息队列的尾部,然后等待Looper调用此runnable的时候,View也已经初始化好了。典型代码如下:

@Override
protected void onStart() {
    super.onStart();
    view.post(new Runnable() {
        @Override
        public void run() {
            int width = view.getMeasuredWidth();
            int height = view.getMeasuredHeight();
        }
    });
}

 

ViewTreeObserver

使用ViewTreeObserver的从多回调可以完成这个功能,比如OnGlobalLayoutListener这个接口,当View树的状态发生改变或者View树内部的View的可见性发生改变时,onGlobalLayout方法将被回调。需要注意的是,伴随着View树的状态改变等,onGlobalLayout会被调用多次。典型代码如下:

@Override
protected void onStart() {
    super.onStart();

    ViewTreeObserver observer = view.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @SuppressWarnings("deprecation")
        @Override
        public void onGlobalLayout() {
            view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            int width = view.getMeasuredWidth();
            int height = view.getMeasuredHeight();
        }
    });
}


 ——本博文部分内容参考自《Android开发艺术探索》

你可能感兴趣的:(Android入门与基础)