在 Activity 的 onCreate() 方法中为什么获取 View 的宽和高为0 ?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_view);
myview = ViewUtils.find(this, R.id.myview);
getViewSize("onCreate");
}
private void getViewSize(String methodTag) {
int width = myview.getWidth();
int height = myview.getHeight();
Log.i(TAG, methodTag + ": width=" + width + " | height=" + height);
}
log如下:
12-15 17:04:55.470 29286-29286/cn.codingblock.view I/MyViewActivity: onCreate: width=0 | height=0
如上面代码结果所示,在Activity的onCreate()方法中我们尝试获取控件的宽和高,却获取得是0,这是因为 View 绘制和 Activity 的生命周期方法并不同步,即使 Activity 回调了 onCreate()、onStart()、onResume() 方法,View 也不一定同步完成绘制,所以此时在这些方法里面获取 View 的尺寸时就获取不到,解决方法有以下几种:
方法一、在 Activity 的 onWindowFocusChanged() 方法中获取 View 的尺寸。
在 Activity 中,当对所有的 View 初始化完毕后,会回调 onWindowFocusChanged() 方法。
/**
* 方案一
* 当 View 初始化完毕是回调
* 当 Activity 每次获取和失去焦点时回调
* @param hasFocus
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
getViewSize("onWindowFocusChanged");
}
方法二、使用 View.post() 将任务post到消息队列中,当view初始化完毕后looper会执行任务。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_view);
myview = ViewUtils.find(this, R.id.myview);
// 方案二、将任务post到消息队列中,当view初始化完毕后looper会执行任务
myview.post(new Runnable() {
@Override
public void run() {
getViewSize("post");
}
});
}
方法三、可以使用 ViewTreeObserver 的一些监听接口。
例如:当 View 树的状态或者 View 树内部的 View 的可见性发生改变时,ViewTreeObserver.OnGlobalLayoutListener 接口的 onGlobalLayout() 会被回调,可以在此方法内部获取 View 的尺寸。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_view);
myview = ViewUtils.find(this, R.id.myview);
// 方案三、当 View 树的状态或者 View 树内部的 View 的可见性发生改变时,
// ViewTreeObserver.OnGlobalLayoutListener 接口的 onGlobalLayout() 会被回调,
// 可以在此方法内部获取 View 的尺寸
ViewTreeObserver observer = myview.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
getViewSize("onGlobalLayout");
}
});
}
当然除了以上方法之外还会有其他的方法,例如可以使用延时或者在onCreate()方法中手动调用 View 的测量方法,相对而言以上几种方法更为方便。
最后
无论您是刚刚开始学习Android开发,还是已经有一定经验的开发者,亦或是想要进阶和突破20~30K薪资范畴。学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈
如果你没有方向,这里分享一份涵盖了从基本的Android开发到高级知识内容的《Android十大模块进阶笔记》,包括车载开发、UI设计,Android Framework底层原理等方面。这份学习笔记不仅深入浅出,而且非常实用,让大家系统而高效地掌握Android开发的各个知识点
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
另外还有腾讯薪选认证的Android移动架构成长路线图,帮助大家查漏补缺,理顺以后发展路线。
全套视频资料:
一、面试合集
二、源码解析合集
三、开源框架合集
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓