1、View的getWidth() 和 getMeasuredWidth()有什么区别?
2、如何在onCreate中拿到View的宽度和高度?
一、 View的getWidth() 和 getMeasuredWidth()有什么区别?
getWidth()是最终宽度,getMeasuredWidth()是测量宽度。
两方法严格来说是有区别的,先看下getWidth()源码
public final int getWidth(){return mRight-mLeft;}
mLeft、mRight、mTop、mBottom:View的位置坐标相对于父view的坐标
进入正题:在View的默认实现中,View的测量宽高和最终宽高是相等的,只不过测量宽/高形成于View的measure过程,而最终宽/高形成于View的layout过程,即两者的赋值时机不同,测量宽/高的赋值时机稍微早些。
因此,在日常开发中,我们可以认为View的测量宽/高和最终宽/高是相等的,在某些特殊的情况下是不相等,比如重写了onLayout方法。
二、如何在onCreate中拿到View的宽度和高度?
在OnCreate、onStart、onResume中均无法正确的拿到某一个View的宽高,这是因为View的measure过程和Activity的生命周期方法不同步,因此无法保证Activity执行了OnCreate、onStart、onResume时某个View已经测量完毕了,如果还没测量完毕,那么拿到的宽高就是0。
常用的解决方案有三种。
- 1 、Activity/View#onWindowFocusChanged
onWindowFocusChanged这个方法的含义是:View已经初始化完毕了,宽/高已经准备好了。需要注意的是,onWindowFocusChanged会被调用多次,当Activity的窗口获取焦点和市区焦点的时候均会被调用一次。具体来说,如果频繁的进行onResume和onPause,那么onWindowFocusChanged也会被频繁的调用。典型的代码如下:
public void onWindowFocusChanged(boolean hasFocus){
super.onWindowFocusChanged(hasFous);
if(hasFocus){
int width =view.getMeasuredWidth();
int height=view.getMeasuredHeight();
}
}
- 2、 view.post(runnable)
通过post将一个runnable投递到信息队列的尾部,然后等Looper调用此runnable的时候,View也初始化完成了。典型的代码如下:
protected void onStart(){
super.onStart();
view.post(new Runnable(){
@Override public voiud run(){
int width =view.getMeasuredWidth();
int height=view.getMeasuredHeight();
}
});
}
- 3、ViewTreeObserver
使用ViewTreeObserver的众多回调可以完成这个功能,比如使用OnGlobalLayoutListener这个接口,当View树的状态改变或View树内部的View的可见性改变时,onGlobalLayout方法将被回调,因此这是获取View宽、高的好时机。需要注意的是,伴随着View树的改变等,onGlobalLayout会被调用多次。
protected void onStart(){
super.onStart();
ViwwTreeOberver observer=view.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener(){
@SuppressWarnings("desprecation")
@Override
public void onGlobalLayout(){
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width =view.getMeasuredWidth();
int height=view.getMeasuredHeight();
}
});
}
网友评论