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

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

那么在onCreate()获取view的width和height会得到0呢,原因是Android的oncreate和onMesure是不同步的,我们在onCreate里面获取的width和height,控件还没有绘制完成呢。

针对上面的问题,网上提供了4种解决方案:

1,View.post()

此方法的思路是在onCreate里面执行一个线程,知道获取View的宽高属性。

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

2,ViewTreeObserver

ViewTreeObserver监听不同的界面绘制事件。一般来说OnGlobalLayoutListener就是可以让我们获得到view的width和height的地方

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

3,onWindowFocusChanged()

当Activity的当前Window获得或失去焦点时会被回调此方法。我们看一下其调用顺序为Activity.oncreate()→Activity.onResume()→
→TestImageView.onMeasure()→TestImageView.onLayout()→onGlobalLayoutListener()→Activity.onWidnowFocusChanged()→.....→
→TextImageView.onDraw()。

所以在onWindowFocusChanged获取的也是不为0的。

4,重写View的onLayout方法

我们知道Android的view绘制流程中是onMesure->onLayout()的顺序,所以在onLayout获取的也是真实的数据。

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
    }
};
时间: 2024-08-02 22:56:12

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

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

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

解决Android从相册中获取图片出错图片却无法裁剪问题的方法_Android

在学习获取相册中图片进行裁剪的时候遇到了比较大的问题,在纠结了近半天才真的解决,下面分享一下学习经验. 问题: 选择了相册中的图片之后要进入图片裁剪的时候出错,(华为)手机提示"此图片无法获取",经百度后,明白是版本不同导致的URI的问题的问题,原文如下: 4.3或以下,选了图片之后,根据Uri来做处理,很多帖子都有了,我就不详细说了.主要是4.4,如果使用上面pick的原生方法来选图,返回的uri还是正常的,但如果用ACTION_GET_CONTENT的方法,返回的uri跟4.3是完

Android开发中获取View视图宽与高的常用方法小结

本文实例讲述了Android开发中获取View视图宽与高的常用方法.分享给大家供大家参考,具体如下: 一.根据WindowManager管理器获得 1)这两种方法在屏幕未显示的时候,还是处于0的状态,即要在setContentView调用之后才有效. 2)Activity必须如此设置才能获得view的宽高 //设置为无标题 requestWindowFeature(Window.FEATURE_NO_TITLE); //设置为全屏模式getWindow().setFlags(WindowMana

解决SQL订阅过程中找不到已经创建的订阅

原文:解决SQL订阅过程中找不到已经创建的订阅 之前有写过一篇博客,主要是图解SQL复制技术:图解SQL 2008数据库复制,当时的测试环境是在我本地同一个服务器上面,所以测试的时候可谓是一帆风顺,最近公司要做一个数据同步的事物,所以再次在不同的服务器测试一次,发现当订阅服务创建成功之后,在本地订阅的根目录里面根本找不到所创建的订阅,但是重新创建的话,SQL又会提示当前订阅已经存在,如下错误截图: 检查了很多次,一直未发现异常,后来想到防火墙,打开本地的防火墙之后,发现确实是启用状态,于是关闭本

已成功与服务器建立连接,但是在登录过程中发生错误。 (provider: SSL Provider, error: 0 - 接收到的消息异常,或格式不正确。)

之前做好的asp.net部署后,发现 访问数据库时: 异常:已捕获: "已成功与服务器建立连接,但是在登录过程中发生错误. (provider: SSL Provider, error: 0 - 接收到的消息异常,或格式不正确.)" (System.Data.SqlClient.SqlException)捕获到一个 System.Data.SqlClient.SqlException: "已成功与服务器建立连接,但是在登录过程中发生错误. (provider: SSL Pro

sharepoint 2013-求问各位大神在SharePoint 2013中 获取list下所有column的名字和值得方法

问题描述 求问各位大神在SharePoint 2013中 获取list下所有column的名字和值得方法 现在在SharePoint开发遇到难题,想要获取某个list中的所有column的名字和对应的值得种类.本来想的只要找到column的头上下拉列表中对应的字段,就可以全找到了,但这个实在找不到.求问获取column的name和value的方法,多谢各位大神解救啊 解决方案 首先连接sharePoint找到每一列的属性,在属性里有你想要的name和类型. 在VS的右上角有连接sharePoin

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

 我们重点在获取view的y坐标,你懂的... 依次介绍以下四个方法:   1.getLocationInWindow   int[] position = new int[2];  textview.getLocationInWindow(position);  System.out.println("getLocationInWindow:" + position[0] + "," + position[1]);  这个方法是将view的左上角坐标存入数组中.此

在Java的应用过程中获取系统属性

Java语言以其面向对象.跨平台.可移植性好.安全性高等优点,受到众多编程人员的青睐,越来越多的人将其作为应用软件开发语言的首选. 在Java应用程序运行时,特别是需要在跨平台工作环境下运行时,需要确定操作系统类型.用户JDK版本和用户工作目录等随工作平台变化的信息,来保证程序正确运行.一般情况下,可以利用JDK提供的系统属性类(Properties)中的方法,快速地获取工作环境信息. 另外,程序开发人员还可以定义与应用程序相关的系统属性文件,在用户程序执行过程中动态地加载程序员定义的属性文件来

SQL疑难杂症【2】解决SQL订阅过程中找不到已经创建的订阅

之前有写过一篇博客,主要是图解SQL复制技术:图解SQL 2008数据库复制,当时的测试环境是在我本地同一个服务器上面,所以测试的时候可谓是一帆风顺,最近公司要做一个数据同步的事物,所以再次在不同的服务器测试一次,发现当订阅服务创建成功之后,在本地订阅的根目录里面根本找不到所创建的订阅,但是重新创建的话,SQL又会提示当前订阅已经存在,如下错误截图: 检查了很多次,一直未发现异常,后来想到防火墙,打开本地的防火墙之后,发现确实是启用状态,于是关闭本地的防火墙,再次刷新本地订阅,之前创建的订阅已经