很经常当我们动态创建某些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过程后调用。

 view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mScrollView.post(new Runnable() {
public void run() {
view.getHeight(); //height is ready
}
});
}
});

但是要注意这个方法在每次有些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发生变化后执行。

 final View view=//smth;
...
view.post(new Runnable() {
@Override
public void run() {
view.getHeight(); //height is ready
}
});

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

参考:
http://stackoverflow.com/a/3602144/774398
http://stackoverflow.com/a/3948036/774398

3、重写View的onLayout方法

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

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

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

附加:获取固定宽高

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

 View.getMeasureWidth()
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

解决在onCreate()过程中获取View的width和Height为0的4种方法的更多相关文章

  1. 解决在onCreate()过程中获取View的width和Height为0的方法

    最近在看Android底层代码的view绘制原理的时候讲到一个很有意思的事情,也是我几年前刚开始学习Android开发的时候比较纳闷的一个问题,如果你不理解Android的底层绘制,请看我之前一片文章 ...

  2. 解决获取View的width和Height为0的4种方法

    很经常当我们动态创建某些View时,需要通过获取他们的width和height来确定别的view的布局,但是在onCreate()获取view的width和height会得到0.view.getWid ...

  3. iPad中控制器view的width和height

    一.iPad中控制器view的width和height 1> 规律 * width 是宽高中最小的那个值 * height 是宽高中最大的那个值 2> 举例(比如窗口根控制器的view,有 ...

  4. Activity中获取view的高度和宽度为0的原因以及解决方案

    在activity中可以调用View.getWidth.View.getHeight().View.getMeasuredWidth() .View.getgetMeasuredHeight()来获得 ...

  5. 简析Geoserver中获取图层列表以及各图层描述信息的三种方法

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 实际项目中需要获取到Geoserver中的图层组织以及各图层 ...

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

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

  7. 如何在onCreate中获取View的高度和宽度

    如何在onCreate中获取View的高度和宽度 原文链接:http://mp.weixin.qq.com/s?__biz=MzAwODE1NTI2MQ==&mid=2247483676&am ...

  8. spring mvc DispatcherServlet详解之三---request通过ModelAndView中获取View实例的过程

    整个spring mvc的架构如下图所示: 上篇文件讲解了DispatcherServlet第二步:通过request从Controller获取ModelAndView.现在来讲解第三步:reques ...

  9. android应用程序中获取view的位置

    我们重点在获取view的y坐标,你懂的... 依次介绍以下四个方法: 1.getLocationInWindow int[] position = new int[2]; textview.getLo ...

随机推荐

  1. visul studio 文件分包

    1.搜索算法. 2.软件控制逻辑. 3.自定义控件. 4.GUI模块. 5.线程化操作

  2. 第三次作业——《K米评测》

    第三次作业--<K米评测> 一.调研.评测 上手体验 APP的图标做的不错,一眼就知道和KTV唱歌相关的 点进去就是连接包箱的界面和直播界面,把软件最重要的两个功能展示出来了,一目了然 热 ...

  3. 由React学习到Yeoman安装以及遇到的问题

    离职闲下来之后想着学一些新知识,本来是想从react入手,结果延伸出去的内容就像一棵树的树枝,不断增加. 学习计划是从这里开始的(6周学习计划,攻克javascript难关 https://zhuan ...

  4. 把页面上的图表导出为pdf文件,分享一种请求下载文件的方法

    最近客户提出一个需求,就是把页面上的图表导出为pdf文件. 找了很多资料.终于有了点头绪.最主要是参考了HighCharts的做法.http://www.hcharts.cn/ 实现原理:把页面图表的 ...

  5. the fourth class

    6 居右 label加宽度,text-align:right 7 list copy: list1.concat(list1) 8 灵活运用addHandle,addEventListener 给in ...

  6. 【如何在mysql 官网下载最新版本mysql 数据库】

    方法/步骤   打开百度搜索,输入MySQL,第一个是MySQL官网   点击第一个链接地址,进入MySQL官方网站,单击“Downloads”下载Tab页,进入下载界面   找到Community( ...

  7. iOS 报错 :Duplicate interface definition for class’*'

    这个是重复导入引起的,但是一般的重复导入会在C里的include.而在项目中我们移动项目的位置,比如从某一文件夹移到另一文件夹,路径改变的话会导致项目的中预编译文件PrefixHeader.pch的路 ...

  8. C# 直接调用vs 委托vs动态调用vs动态类型vs反射,最佳性能测试

    懒得解释,自己看代码 测试结果: Direct call:00:00:00.0742191Delegate Direct:00:00:00.0687487Method Factory(IL):00:0 ...

  9. H5 canvas填充文字自动换行

    canvas是H5中非常重要,非常常用,也是非常强大的一个新标签,美中不足的事,canvas中没没有自动换行的属性,我的第一反应是,字符串截取,然后计算每行的距离来实现自动换行.. 然后百度了一下,已 ...

  10. CSDDN特约专稿:个性化推荐技术漫谈

    本文引自http://i.cnblogs.com/EditPosts.aspx?opt=1 如果说过去的十年是搜索技术大行其道的十年,那么个性化推荐技术将成为未来十年中最重要的革新之一.目前几乎所有大 ...