Android开发中getMeasuredWidth为0时的解决方法

我们在日常开发中,经常需要获取控件的长度和高度。而使用getMeasuredWidth()和getMeasuredHeight()方法,无论是在onCreate()onStart()onResume()中调用,都无法得到控件的长度、和宽度。如下图,测量的结果为0。


Android开发艺术探索》中给出了答案,因为ViewMeasure过程和Activity的生命周期方法不是同步执行的,所以无法保证Activity执行了onCreate()onStart()onResume()时某个View已经测量完毕了,如果View还没有测量完毕,那么获得宽/高就是0。

针对这个问题,书中给出4个解决方法:


1.Activity中onWindowFocusChanged方法

onWindowFocusChanged方法表示,View已经初始化完毕,宽高已经准备好了,这时执行getMeasuredWidth()和getMeasuredHeight()方法,便可以获取宽高,常用代码如下:

Android开发中getMeasuredWidth为0时的解决方法_第1张图片

结果如下如下图所示:


当然也存在问题,onWindowFocusChanged会被调用多次,当Activity窗口得到或失去焦点时均会被调用。

 

2.View.post(runnable)

通过post可以将一个runnable投递到消息队列的尾部,然后等待Looper调用runnable的时候,View也已经初始化好了,代码如下:

Android开发中getMeasuredWidth为0时的解决方法_第2张图片

结果如下:


3.ViewTreeObserver

使用ViewTreeObserver的众多回调可以完成这个功能,比如使用OnGlobalLayoutListener这个接口,当View树的状态发生改变或者View树内部的View的可见性发生改变时,onGlobalLayout方法将被回调,因此这是获取View的宽高一个很好的时机。当然伴随着View树的状态改变,onGlobalLayout会被多次调用。代码如下:


Android开发中getMeasuredWidth为0时的解决方法_第3张图片

Log结果如下:

3.View.measure(int widthMeasureSpec,int heightMeasureSpec)

通过手动对View进行measure来得到View的宽高。本方法较复杂,分情况处理,当然先得了解ViewMeasureSpec创建规则,这里推荐不了解的朋友,参考Android 《从 开始自定义控件之深入理解 MeasureSpec ,当然也是参考与《Android开发艺术探索》。

了解之后,可以具体分情况来处理:

Match_parent

该方法直接放弃,无法测出具体宽高,原因很简单,根据Viewmeasure过程,该情况需要知道父控件大小,然而这里我们无法知道父控件大小,理论上不可能测出View的大小。


具体的数值(dp/px

比如宽高都是100px,如下measure:


日志如下:


Wrap_content


日志如下:


View的尺寸使用30位二进制表示,也就是说最大是30个1(2^30-1),也就是(1<<30)-1,在最大化模式下,用View理论桑能支持的最大值去构造MeasureSpec 是合理的。

 

 

书中提及ViewMeasure,网络上有两个错误用法。主要首先其违反了系统内部实现规范(因为无法通过错误的MeasureSpec 去得出合法的SpecMode,从而导致measure过程出错),其次不能保证一定能measure出正确的结果。

 

第一种错误用法

:

第二种错误用法:




你可能感兴趣的:(Android)