实际上在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开发艺术探索》