在 Activity 的 onCreate() 方法中为什么获取 View 的宽和高为0 ?

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. setContentView(R.layout.activity_my_view);
  5. myview = ViewUtils.find(this, R.id.myview);
  6. getViewSize("onCreate");
  7. }
  8. private void getViewSize(String methodTag) {
  9. int width = myview.getWidth();
  10. int height = myview.getHeight();
  11. Log.i(TAG, methodTag + ": width=" + width + " | height=" + height);
  12. }

log如下:

  1. 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 的尺寸。

  1. Activity 中,当对所有的 View 初始化完毕后,会回调 onWindowFocusChanged() 方法。
  1. /**
  2. * 方案一
  3. * 当 View 初始化完毕是回调
  4. * 当 Activity 每次获取和失去焦点时回调
  5. * @param hasFocus
  6. */
  7. @Override
  8. public void onWindowFocusChanged(boolean hasFocus) {
  9. super.onWindowFocusChanged(hasFocus);
  10. getViewSize("onWindowFocusChanged");
  11. }

方法二、使用 View.post() 将任务post到消息队列中,当view初始化完毕后looper会执行任务。

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. setContentView(R.layout.activity_my_view);
  5. myview = ViewUtils.find(this, R.id.myview);
  6. // 方案二、将任务post到消息队列中,当view初始化完毕后looper会执行任务
  7. myview.post(new Runnable() {
  8. @Override
  9. public void run() {
  10. getViewSize("post");
  11. }
  12. });
  13. }

方法三、可以使用 ViewTreeObserver 的一些监听接口。

  1. 例如:当 View 树的状态或者 View 树内部的 View 的可见性发生改变时,ViewTreeObserver.OnGlobalLayoutListener 接口的 onGlobalLayout() 会被回调,可以在此方法内部获取 View 的尺寸。
  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. setContentView(R.layout.activity_my_view);
  5. myview = ViewUtils.find(this, R.id.myview);
  6. // 方案三、当 View 树的状态或者 View 树内部的 View 的可见性发生改变时,
  7. // ViewTreeObserver.OnGlobalLayoutListener 接口的 onGlobalLayout() 会被回调,
  8. // 可以在此方法内部获取 View 的尺寸
  9. ViewTreeObserver observer = myview.getViewTreeObserver();
  10. observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  11. @Override
  12. public void onGlobalLayout() {
  13. getViewSize("onGlobalLayout");
  14. }
  15. });
  16. }

当然除了以上方法之外还会有其他的方法,例如可以使用延时或者在onCreate()方法中手动调用 View 的测量方法,相对而言以上几种方法更为方便。


最后想说的是,本系列文章为博主对Android知识进行再次梳理,查缺补漏的学习过程,一方面是对自己遗忘的东西加以复习重新掌握,另一方面相信在重新学习的过程中定会有巨大的新收获,如果你也有跟我同样的想法,不妨关注我一起学习,互相探讨,共同进步!

参考文献:

  • 《Android开发艺术探索》
  • 《Android开发进阶从小工到专家》

Android查缺补漏(View篇)--在 Activity 的 onCreate() 方法中为什么获取 View 的宽和高为0?的更多相关文章

  1. Android查缺补漏(View篇)--自定义 View 的基本流程

    View是Android很重要的一部分,常用的View有Button.TextView.EditView.ListView.GridView.各种layout等等,开发者通过对这些View的各种组合以 ...

  2. Android查缺补漏(View篇)--事件分发机制源码分析

    在上一篇博文中分析了事件分发的流程及规则,本篇会从源码的角度更进一步理解事件分发机制的原理,如果对事件分发规则还不太清楚的童鞋,建议先看一下上一篇博文 <Android查缺补漏(View篇)-- ...

  3. Android查缺补漏(IPC篇)-- Bundle、文件共享、ContentProvider、Messenger四种进程间通讯介绍

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8387752.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  4. Android查缺补漏(IPC篇)-- 款进程通讯之AIDL详解

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  5. Android查缺补漏(线程篇)-- IntentService的源码浅析

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8975114.html 在Android中有两个比较容易弄混的概念,Servic ...

  6. Android查缺补漏(IPC篇)-- 进程间通讯之AIDL详解

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  7. Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8479282.html 在Android中进程间通信是比较难的一部分,同时又非常 ...

  8. Android查缺补漏(IPC篇)-- 进程间通讯之Socket简介及示例

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8425736.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  9. Android查缺补漏(View篇)--自定义View利器Canvas和Paint详解

    上篇文章介绍了自定义View的创建流程,从宏观上给出了一个自定义View的创建步骤,本篇是上一篇文章的延续,介绍了自定义View中两个必不可少的工具Canvas和Paint,从细节上更进一步的讲解自定 ...

随机推荐

  1. [转载] redis 的两种持久化方式及原理

    转载自http://www.m690.com/archives/371 Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串 ...

  2. Linux nc 命令传输文件

    NAME nc - arbitrary TCP and UDP connections and listensSYNOPSIS     nc [-46DdhklnrStUuvz] [-i interv ...

  3. 使用MongoVUE

    mongoDB版本号为3.4.10 在终端操作一顿后想看看它在可视化工具里面什么样子,于是就找了一个可视化工具,MongoVUE这个看起来还不错,因为我是windows系统所以就没有太多的挑选选择.在 ...

  4. 隐藏17年的Office远程代码执行漏洞(CVE-2017-11882)

    Preface 这几天关于Office的一个远程代码执行漏洞很流行,昨天也有朋友发了相关信息,于是想复现一下看看,复现过程也比较简单,主要是简单记录下. 利用脚本Github传送地址 ,后面的参考链接 ...

  5. 【Java框架型项目从入门到装逼】第三节 - 如何用Tomcat发布web项目?

    啥叫Tomcat?有道词典是这么说的. 这个我们姑且不管,实际上呢,Tomcat是一种Web服务器,我们自己做好了一个Web项目,就可以通过Tomcat来发布.服务器呢,又分为硬件服务器和软件服务器. ...

  6. LKD: Chapter 9 An Introduction to Kernel Synchronization

    This chapter introduces some conception about kernel synchronization generally. Critical Regions: Co ...

  7. Python基础-数据类型和变量

    数据类型 python中包含6种标准数据类型:1.Number 数值类型2.String 字符串类型3.List 列表类型4.Tuple 元祖类型5.Dict 字典类型6.Set 集合类型 注意:除了 ...

  8. 企业级Tomcat部署实践及安全调优

    1.1 Tomcat简介 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun和其他一些公司及个人 ...

  9. 解决div里面img标签后面跟着空白符

    直接在div里面添加img标签有一个坑,img的高度会莫名添加几个像素的高度,查询之后才知道原来css2出现的问题. 引起这个问题原来是img标签默认基线引起的,vertical-align:base ...

  10. hdu 1496 Equations hash表

    hdu 1496 Equations hash表 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1496 思路: hash表,将原来\(n^{4}\)降 ...