在渲染前获取 View 的宽高

这是一个比较有意义的问题,或者说有难度的问题,问题的背景为:有时候我们需要在view渲染前去获取其宽高,典型的情形是,我们想在onCreate、onStart、onResume中去获取view的宽高。如果大家尝试过,会发现,这个时候view还没有measure好,宽高都为0,那到底该怎么做才能正确获取其宽高呢,下面给出三种方法(还有其他方法, 比如监听器回调等):

Activity/View#onWindowFocusChanged :这个方法表明,view已经初始化完毕了,宽高已经准备好了
view.post(runnable) :通过post可以将一个runnable投递到消息队列的尾部,然后等待looper调用此runnable的时候,view也已经初始化好了
view.measure(int widthMeasureSpec, int heightMeasureSpec) :通过手动去measure来视图得到view的宽高

前两种方法都比较好理解也比较简单,这里主要介绍下第三种方法的详细用法:

采用 view.measure 去提前获取 view 的宽高,根据 view 的 layoutParams 来分
1,match_parent
直接放弃,无法 measure 出具体的宽高
2,具体的数值( dp/px )
比如宽高都是 100px ,如下 measure :
    int widthMeasureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY);
    int heightMeasureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY);
    view.measure(widthMeasureSpec, heightMeasureSpec);
3,wrap_content
如下 measure :
    int widthMeasureSpec = MeasureSpec.makeMeasureSpec( (1 << 30) - 1, MeasureSpec.AT_MOST);
    int heightMeasureSpec = MeasureSpec.makeMeasureSpec( (1 << 30) - 1, MeasureSpec.AT_MOST);
    view.measure(widthMeasureSpec, heightMeasureSpec);

注意到(1 << 30) - 1,通过分析MeasureSpec的实现可以知道,view的尺寸使用30位二进制表示的,也就是说最大是30个1即 2^30 - 1,也就是(1 << 30) - 1,在最大化模式下,我们用view理论上能支持的最大值去构造MeasureSpec是合理的。

关于view的measure,网络上有两个错误的用法,如下,为什么说是错误的,首先违背了系统的内部实现规范(因为无法通过错误的MeasureSpec去得出合法的SpecMode从而导致measure出错),其次不能保证一定能 measure 出正确的结果。

第一种错误用法
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(-1, MeasureSpec.UNSPECIFIED);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(-1, MeasureSpec.UNSPECIFIED);
view.measure(widthMeasureSpec, heightMeasureSpec);

第二种错误用法
view.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)

在渲染前获取 View 的宽高的更多相关文章

  1. 用addOnGlobalLayoutListener获取View的宽高

    首先,我们在onCreate方法里调用getHeight()和 getWidth()是不能正确获取View的宽高的,因为onCreate方法执行完了,我们定义的控件才会被onMeasure()度量,所 ...

  2. 监听视图树 ViewTreeObserver 获取View的宽高

    前奏:在哪里可以获取到View的宽高 我们知道,在onCreate方法执行完毕以后,View才开始被测量,所以我们在onCreate方法里面通过view.getWidth()或view.getMeas ...

  3. 通过View.post()获取View的宽高

    在Android里,获取View宽高的时机是个老生常谈的话题了.众所周知,在Oncreate里直接调用View.getWidth或者View.getMeasuredWidth返回都是0.所以获取宽高时 ...

  4. Android查缺补漏(View篇)--在 Activity 的 onCreate() 方法中为什么获取 View 的宽和高为0?

    在 Activity 的 onCreate() 方法中为什么获取 View 的宽和高为0 ? @Override protected void onCreate(Bundle savedInstanc ...

  5. js获取隐藏元素宽高的方法

    网上有一些js获取隐藏元素宽高的方法,但是可能会存在某些情况获取不了. 例如: <!DOCTYPE html> <html lang="en"> <h ...

  6. 前端 JS 获取 Image 图像 宽高 尺寸

    前端 JS 获取 Image 图像 宽高 尺寸 简介 项目中用到获取图片的原始尺寸,然后适配宽高:网上的大部分前端解决方案,都是new Image()后,在onload事件中获取image的尺寸. 在 ...

  7. js判断图片加载完成后获取图片实际宽高

    通常,我们会用jq的.width()/.height()方法获取图片的宽度/高度或者用js的.offsetwidth/.offsetheight方法来获取图片的宽度/高度,但这些方法在我们通过样式设置 ...

  8. RT/Metro商店应用如何如何获取图片的宽高

    RT/Metro商店应用如何如何获取图片的宽高 var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms ...

  9. JS获取图片实际宽高及根据图片大小进行自适应

    JS获取图片实际宽高,以及根据图片大小进行自适应  <img src="http://xxx.jpg" id="imgs" onload="ad ...

随机推荐

  1. [css]我要用css画幅画(九) - Apple Logo

    接着之前的[css]我要用css画幅画(八) - Hello Kitty,这次画的是苹果公司的logo 这次打算将分析和实现步骤尽量详细的说一说. 其实之前的也打算详细讲分析和设计过程,不过之前的图比 ...

  2. [分享] 很多人手机掉了,却不知道怎么找回来。LZ亲身经历讲述手机找回过程,申请加精!

    文章开头:(LZ文笔不好,以下全部是文字描述,懒得配图.因为有人说手机掉了,他们问我是怎么找回来的.所以想写这篇帖子.只不过前段时间忙,没时间.凑端午节给大家一些经验) 还是先谢谢被偷经历吧!5月22 ...

  3. form表单取消按钮自动提交

    默认写在form表单里的按钮可以自动提交表单,现在要实现的效果是点击button按钮调用js函数,再有ajax提交 <button type="button" class=& ...

  4. nodejs处理get请求

    主要记录下获取get请求里面的参数的问题. 假设有这样一个链接 urlString='hello?name=LiLei&position=general' 要从这个链接里提取出参数name和p ...

  5. 每天一个linux命令(3):pwd命令

    Linux中用 pwd 命令来查看”当前工作目录“的完整路径. 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录. 在不太确定当前位置时,就会使用pwd来判定当前目录在文件系统内的确切位置. ...

  6. spring3.0+mybatis+spring快速入门

    一.首先奉上项目目录结构: 说明: dao,mapping,model包下的所有内容可以使用Generator工具自助生成. 具体用法,可以网上学习一下,比较简单,主要做以下工作: 1.提供相关的数据 ...

  7. Linux File Recovery Study

    Background Today I did stupid things that I went into the ~/Downloads/ and pressed [Alt] + [A] then ...

  8. JavaScript获取客户端计算机硬件及系统等信息的方法

    JavaScript获取客户端计算机硬件及系统等信息的方法 JavaScript 获取客户端计算机硬件及系统信息 通过WMI来实现获取客户端计算机硬件及系统信息: function getSysInf ...

  9. oracle 密码有效期

    oracle的密码是存在有效期的,有时候会遇到密码到期需要重设的情况,查看当前密码有效期的语句: SELECT * FROM dba_profiles s WHERE s.profile='DEFAU ...

  10. [No000080]右键解锁增强Chrome插件开发,破除防复制

    昨天用360极速(虽然我不喜欢360.)浏览器,登陆知乎查阅一些东西,突然感觉有些观点很赞同,想copy转载一下,我了个去,它丫的居然不让我复制. 地址:https://www.zhihu.com/q ...