原文地址:https://blog.csdn.net/chenbaige/article/details/77991594ide
可能不少状况下,咱们都会有在activity中获取view 的尺寸大小(宽度和高度)的需求。面对这种状况,不少同窗立马反应:这么简单的问题,还用你说?你是否是傻。。而后立马写下getWidth()、getHeight()等方法,洋洋得意的就走了。然而事实就是这样的吗?实践证实,咱们这样是获取不到View的宽度和高度大小的,可能不少同窗又会纳闷了,这是为何呢?一直不都是这样获取大小的嘛!post
实际状况下,View的measure过程和Activity的生命周期方法不是同步执行的,所以没法保证Activity在执行完某个生命周期方法时View已经测量完毕了,这种状况下,获取到的尺寸大小就是0。所以,在不少状况下,咱们正在为咱们机智而得意时,事实却让咱们大跌眼镜,甚是尴尬。this
接下来咱们介绍四种方式去正确的获取View的尺寸大小。spa
onWindowFocusChanged方法执行时表明View已经初始化完毕了,宽度和高度已经测量完毕而且最终确认好了,这时咱们能够放心的在这里去获取View 的宽度和高度。代码以下:
.net
Activity的onWindowFocusChanged中获取view的宽度和高度 @Override public void onWindowFocusChanged(boolean hasWindowFocus) { super.onWindowFocusChanged(hasWindowFocus); if(hasWindowFocus){ int width = view.getMeasuredWidth(); int height = view.getMeasuredHeight(); } }
注意:虽然使用很方便,但在使用这个方法时须要特别注意:onWindowFocusChanged会执行屡次,在Activity获取焦点和失去焦点时都会被调用一次。即在onPause和onResume方法被执行时被反复调用。code
经过View.post方法把Runnable对象放到消息队列的末尾,当执行到这个runable方法的时候,View全部的初始化测量方法说明都已经执行完毕了。所以在这里获取的时候就是测量后的真实值。代码以下:
Activity经过mView.post方法获取server
mView.post(new Runnable() { @Override public void run() { int width = mView.getMeasuredWidth(); int height = mView.getMeasuredHeight(); } });
当View树的状态发生改变或者View树内部View的可见性发生改变的时候,onGlobalLayout将会被回调。注意:伴随着View树的状态改变,onGlobalLayout会被调用屡次。实现以下:
在Activity生命周期方法中经过ViewTreeObserver获取对象
ViewTreeObserver observer = mView.getViewTreeObserver(); observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { mView.getViewTreeObserver().removeOnGlobalLayoutListener(this); int width = mView.getMeasuredWidth(); int height = mView.getMeasuredHeight(); } });
手动调用measure后,View会调用onMeasure方法对View发起测量,测量完后,就能够获取测量后的宽度和高度了。可是要对LayoutParams的参数分状况处理才能获得具体的参数值:
View的LayoutParams参数为match_parent:这种状况下没法获取到具体宽高值,由于当View的测量模式为match_parent时,宽高值是取父容器的剩余空间大小做为它本身的宽高。而这时没法获取到父容器的尺寸大小,所以获取会失败。
View的LayoutParams参数为具体值:
blog
int width =View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.EXACTLY); int height =View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.EXACTLY); view.measure(width,height); int height=view.getMeasuredHeight(); int width=view.getMeasuredWidth();
View的LayoutParams参数为wrap_content:
生命周期
int width =View.MeasureSpec.makeMeasureSpec((1<<30)-1,View.MeasureSpec.AT_MOST); int height =View.MeasureSpec.makeMeasureSpec((1<<30)-1,View.MeasureSpec.AT_MOST); view.measure(width,height); int height=view.getMeasuredHeight(); int width=view.getMeasuredWidth();