专栏首页风吹杨柳实现杂记(27):解决在onCreate()过程中获取View的width和Height为0的4种方法

实现杂记(27):解决在onCreate()过程中获取View的width和Height为0的4种方法

PS:这个文章是站在巨人的肩膀上抄袭的,之所以再次写,我是想分析:到底是在什么时候拿到宽高

下面的三种方法都经过实际测试,都是可以用的,输出结果如下:

从这个结果可以看出,都是在onResume之后才开始拿到这值的,

使用  onLayout()方法得到的结果,会在第一次输出,当然这个函数会执行很多次,例如后面的又输出来一次,

其中subview输出的是将view自定义,在initView方法中使用view.post输出,这个排在第二位

紧接着:width是在activity中使用view.post方法输出的,排在第三位

后面的GlobalLayoutListener Width 也是在onResume之后输出的,

也就是说:我们想拿到宽和高,都是在onResume这个周期之后才可以拿的到的,

其实也就是在layout之后才拿到的

关于该代码的工程包等我下次更新的时候上传,或者留言,我发你邮箱

http://www.cnblogs.com/kissazi2/p/4133927.html

很经常当我们动态创建某些View时,需要通过获取他们的width和height来确定别的view的布局,但是在onCreate()获取view的width和height会得到0.view.getWidth()和view.getHeight()为0的根本原因是控件还没有完成绘制,你必须等待系统将绘制完View时,才能获得。这种情况当你需要使用动态布局(使用wrap_content或match_parent)就会出现。一般来讲在Activity.onCreate(...)、onResume()方法中都没有办法获取到View的实际宽高。所以,我们必须用一种变通的方法,等到View绘制完成后去获取width和Height。下面有一些可行的解决方案。

1、监听Draw/Layout事件:ViewTreeObserver

ViewTreeObserver监听很多不同的界面绘制事件。一般来说OnGlobalLayoutListener就是可以让我们获得到view的width和height的地方.下面onGlobalLayout内的代码会在View完成Layout过程后调用。

1 view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
 2         @Override
 3         public void onGlobalLayout() {
 4             mScrollView.post(new Runnable() {
 5                 public void run() {
 6                     view.getHeight(); //height is ready
 7                 }
 8             });
 9         }
10 });

但是要注意这个方法在每次有些view的Layout发生变化的时候被调用(比如某个View被设置为Invisible),所以在得到你想要的宽高后,记得移除onGlobleLayoutListener:

在 SDK Lvl < 16时使用 public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) 在 SDK Lvl >= 16时使用 public void removeOnGlobalLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)

2、将一个runnable添加到Layout队列中:View.post()

这个解决方案是我最喜欢的,但是几乎没人知道有这个方法。简单地说,只要用View.post()一个runnable就可以了。runnable对象中的方法会在View的measure、layout等事件后触发,具体的参考Romain Guy:

UI事件队列会按顺序处理事件。在setContentView()被调用后,事件队列中会包含一个要求重新layout的message,所以任何你post到队列中的东西都会在Layout发生变化后执行。

1 final View view=//smth;
2 ...
3 view.post(new Runnable() {
4             @Override
5             public void run() {
6                 view.getHeight(); //height is ready
7             }
8         });

这个方法比ViewTreeObserver好: 1、你的代码只会执行一次,而且你不用在在每次执行后将Observer禁用,省心多了。 2、语法很简单

3、重写View的onLayout方法

这个方法只在某些场景中实用,比如当你所要执行的东西应该作为他的内在逻辑被内聚、模块化在view中,否者这个解决方案就显得十分冗长和笨重。

1 view = new View(this) {
2     @Override
3     protected void onLayout(boolean changed, int l, int t, int r, int b) {
4         super.onLayout(changed, l, t, r, b);
5         view.getHeight(); //height is ready
6     }
7 };

需要注意的是onLayout方法会调用很多次,所以要考虑好在这个方法中要做什么,或者在第一次执行后禁用掉你的代码。

附加:获取固定宽高

如果你要获取的view的width和height是固定的,那么你可以直接使用:

1 View.getMeasureWidth()
2 View.getMeasureHeight()

但是要注意,这两个方法所获取的width和height可能跟实际draw后的不一样。官方文档解释了不同的原因:

View的大小由width和height决定。一个View实际上同时有两种width和height值。

第一种是measure width和measure height。他们定义了view想要在父View中占用多少width和height(详情见Layout)。measured height和width可以通过getMeasuredWidth() 和 getMeasuredHeight()获得。 第二种是width和height,有时候也叫做drawing width和drawing height。这些值定义了view在屏幕上绘制和Layout完成后的实际大小。这些值有可能跟measure width和height不同。width和height可以通过getWidth()和getHeight获得。

参考链接

https://stackoverflow.com/questions/3591784/getwidth-and-getheight-of-view-returns-0/24035591#24035591

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 实习入职第二十天:从setRecyclerListener看listView回收机制

    关于这个  setRecyclerListener函数在解决   listView滑出屏幕(包括向上滑出和向下滑出)处理相关UI操作或者释放相关资源,真的很好用...

    wust小吴
  • java学习---------IO流学习---文件流inputstream outputstream

    FileInputStream FileoutputStream FileReader FileWriter

    wust小吴
  • Android基础部分再学习---activity的状态保存

    参考地址:http://blog.csdn.net/lonelyroamer/article/details/18715975

    wust小吴
  • Android自定义控件总结

    六月的雨
  • Python 内建函数大全

    Python 解释器内置了许多函数和类型,列表如下(按字母排序)(省略了几个我没用过或者不常用的)。

    用户2769421
  • Android 应用架构演变

    代码被划分为两层结构:Data Layer(数据层)负责从数据源获取和存储数据;View Layer(视图层)负责处理并将数据展示在UI上

    用户3004328
  • JS - 兼容到ie7的自定义样式的滚动条封装

    xing.org1^
  • 【2019年8月版本】OCP 071认证考试最新版本的考试原题-第9题

    Which three statements are true about views in an Orade batabase?

    用户5892232
  • 真的!人工智能可以预测死亡时间

    使用人工智能来预测患者死亡的时间听起来像反乌托邦科幻电视剧“黑镜”中的一幕。但是斯坦福大学的研究人员认为,AI 的这个用途,可以给医生和病人及早地开始必要的临终...

    机器人网
  • 业界 | 每天1.4亿小时观看时长,Netflix怎样存储这些时间序列数据?

    大数据文摘

扫码关注云+社区

领取腾讯云代金券