如果在Activity启动时想要获取某个view的宽高,发现获取到的是0,这种情况产生的原因是activity启动的时候,view的绘制和activity不是同步执行的,也就是measure还未测量完,如果未测量完就获取宽高的话这时获取到的就是0了
下面介绍四种获取宽高的方法:
1:Activity/View->onWindowFocusChanged
onWindowFocusChanged方法是在view准备工作完成,当activity窗口获取到焦点的时候会调用,当然,在activity在失去焦点的时候也会调用,假如activity在onPause和onStop状态时也会调用
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus){
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
}
2:view.post(runnable)
这种方法会往view的消息列队添加一个消息,并在前面的消息执行完毕后执行次消息,在looper调用此消息的时候,view的初始化工作已经完成,所以这时是可以获取到宽高的
view.post(new Runnable() {
@Override
public void run() {
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
});
3:ViewTreeObserver
ViewTreeObserver的很多回调里面都可以获取,例如addOnGlobalLayoutListener回调,这个回调会在view树内view的layout发生改变时回调,layout是在measure后执行的,所以此时宽高已经可以获取到了
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
});
4:view.measure(int widthMeasureSpec,heightMeasureSpec)
手动测量比较复杂,需要根据LayoutParams进行区分处理
match_parent
这种情况无法测量,因为测量的时候需要知道parentSize,及父容器的剩余空间,但是这时无法获取父容器的剩余空间,所以无法测量
wrap_parent
int measureSpec = View.MeasureSpec.makeMeasureSpec((1<<30) - 1, View.MeasureSpec.AT_MOST);
view.measure(measureSpec,measureSpec);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
View的尺寸,使用30位的二进制表示,最大就是30个1,就是1<<30
固定宽高的
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.AT_MOST);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.AT_MOST);
view.measure(widthMeasureSpec,heightMeasureSpec);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
其他测量方法不能准确测量,暂不推荐