大家好,这篇博文主要是教给大家一个方法,如何在onCreate()方法中获取我们所需的View对象的高度和宽度,大家应该都试验过,在onCreate()方法中通过view.getWidth()方法和view.getHeight()方法得到的结果都是0,那么这是为什么呢?
因为当onCreate()方法被调用时,会调用LayoutInflater将布局文件填充到ContentView。填充过程只包括创建视图,却不包括设置其大小。那么,视图的大小在什么时候指定的呢?
Android开发文档的解释如下:
”绘制由两个遍历过程组成:测量过程和布局过程。测量过程由measure(int,int)方法完成,该方法从上到下遍历视图树。在递归遍历过程中,每个视图都会向下层传递尺寸和规格。当measure方法遍历完成时,每个视图都保存了各自的尺寸信息。第二个过程由layout(int,int,int,int)方法完成,该方法也是从上到下遍历视图树,在遍历过程中,每个父视图通过测量过程的结果定位所有子视图的位置信息。“
- 结论如下:
只有在整个布局绘制完成后,视图才能得到自身的宽和高,这个过程发生在onCreate()方法之后,因此,在此之前调用getWidth()和getHeight()方法返回的结果都是0。
那么我们怎么在onCreate()方法中得到view的宽和高呢?
当然我们是有方法的,那就是通过View的post()方法解决上述问题,该方法接收一个Runnable线程参数,并将其添加到消息队列中,有趣的是Runnable线程会在UI线程中执行。
示例代码和运行log结果如下所示:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.main_clock_time);
Log.e(TAG, "mtextview width is : "+mTextView.getWidth()+", height is : "+mTextView.getHeight() );
mTextView.post(new Runnable() {
@Override
public void run() {
Log.e(TAG, "mtextview width is : "+mTextView.getWidth()+", height is : "+mTextView.getHeight() );
}
});
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
运行结果:
10-26 14:10:40.109 11697-11697/? E/MainActivity: mtextview width is : 0, height is : 0
10-26 14:10:40.149 11697-11697/? E/MainActivity: mtextview width is : 872, height is : 211
可以看到在post方法之前获取到的结果值如我们之前提到的都是0,但是通过post()方法运行在线程中的就能正确的获取到宽和高了。
那我就当然点进去看了看源码咯,View.Java中的post()方法源码如下:
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue().post(action);
return true;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
然后再进入到post(action)方法中,进入到了HandlerActionQueue.java源码中,可以看到post方法源码如下:
public void post(Runnable action) {
postDelayed(action, 0);
}
public void postDelayed(Runnable action, long delayMillis) {
final HandlerAction handlerAction = new HandlerAction(action, delayMillis);
synchronized (this) {
if (mActions == null) {
mActions = new HandlerAction[4];
}
mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);
mCount++;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
可以看到代码也是做了postDelay的处理延时发送消息,所以这才是能正确的获取到宽和高的终极地方了吧。