在项目中,我们要在代码中获取view的宽高信息,有可能就会在onCreat或者onResume方法中去获取,原因就是view的measure过程与Activity的生命周期不是同步执行的,因此无法保证在onCreat,onResume,onStart时这个view是否已经测量完毕,如果没有测量完毕,得到的结果就是0。这里给出4种解决办法
- (1) onWindowFocusChanged
onWindowFocusChanged含义就是view已经初始化完毕,这个时候去获取宽高就没问题了,但是要注意的是此方法会被调用很多次,当Activity的窗口失去或者得到焦点都会调用一次,也就是Activity onResume或onPause时都会调用。典型代码如下:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus){
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
}
- (2) view.post(runnable)
通过post将一个runnable投递到消息队列的尾部,然后等Looper调用此runnable的时候,view也就已经初始化好了,典型代码如下:
@Override
public void onStart() {
super.onStart();
view.post(new Runnable){
@Override
public void run(){
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
}
}
- (3) viewTreeObserver
使用viewTreeObserver的众多回调可以完成这个功能,比如使用OnGlobalLayoutListener这个接口,当view树的状态发生改变或者view树的内部view的可见性发生改变时,onGlobalLayout方法会被调用,因此这是获取view宽高很好的时机。需要注意的是,伴随着view树状态改变onGlobalLayout会被调用很多次,典型代码如下:
@Override
protected void onStart() {
super.onStart();
ViewTreeObserver observer = view.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
});
}
- (4) view.measure(intwidthMeasureSpec,intheightMeasureSpec)
通过手动对view的measure来得到view的宽高,这种方法比较复杂,要分情况处理,根据view的LayoutParams来分: - math_parent
无法测量,因为构造此种MeasureSpec需要知道parentSize,即父容器的剩余空间,而此时我们无法知道parentSize的大小,所以理论上测量不出view的大小。 - 具体数值(dp/px)
比如说宽高都是100px,如下:
int widthMeasureSpec=MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY);
int heightMeasureSpec=MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY);
view.measure(widthMeasureSpec,heightMeasureSpec);
- wrap_content
int widthMeasureSpec=MeasureSpec.makeMeasureSpec((1<<30)-1,MeasureSpec.AT_MOST);
int heightMeasureSpec=MeasureSpec.makeMeasureSpec((1<<30)-1,MeasureSpec.AT_MOST);
view.measure(widthMeasureSpec,heightMeasureSpec);