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

简介:

很经常当我们动态创建某些View时,需要通过获取他们的width和height来确定别的view的布局,但是在onCreate()获取view的width和height会得到0.view.getWidth()view.getHeight()为0的根本原因是控件还没有完成绘制,你必须等待系统将绘制完View时,才能获得。这种情况当你需要使用动态布局(使用wrap_contentmatch_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、语法很简单


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

 

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

本文转自陈哈哈博客园博客,原文链接http://www.cnblogs.com/kissazi2/p/4133927.html如需转载请自行联系原作者


kissazi2

相关文章
|
Android开发
Android Studio APP开发入门之对话框Dialog的讲解及使用(附源码 包括提醒对话框,日期对话框,时间对话框)
Android Studio APP开发入门之对话框Dialog的讲解及使用(附源码 包括提醒对话框,日期对话框,时间对话框)
546 0
|
5月前
|
UED 容器
5.HarmonyOS Next开发宝典:掌握Flex布局的艺术
Flex布局(弹性布局)是HarmonyOS Next中最强大的布局方式之一,它提供了一种更加高效、灵活的方式来对容器中的子元素进行排列、对齐和分配空间。无论是简单的居中显示,还是复杂的自适应界面,Flex布局都能轻松应对。
190 0
|
3月前
|
Shell 网络安全 开发工具
项目快速导入git
本文介绍了如何在本地初始化 Git 仓库并将代码提交到远程仓库(如 GitHub 或 Gitee)的基本流程。内容包括安装 Git、创建仓库、添加文件、提交更改以及推送代码到远程仓库的详细步骤,适合初学者快速掌握 Git 的基本使用方法。
151 1
|
8月前
鸿蒙开发:wrapBuilder来封装全局@Builder
首先第一点,在同一个UI组件内,同一个wrapBuilder只能初始化一次,第二点就是WrappedBuilder对象的builder属性方法只能在struct内部使用。
210 7
|
9月前
|
Android开发 开发者 Kotlin
Android实战经验之Kotlin中快速实现MVI架构
MVI架构通过单向数据流和不可变状态,提供了一种清晰、可预测的状态管理方式。在Kotlin中实现MVI架构,不仅提高了代码的可维护性和可测试性,还能更好地应对复杂的UI交互和状态管理。通过本文的介绍,希望开发者能够掌握MVI架构的核心思想,并在实际项目中灵活应用。
413 8
|
11月前
|
安全 Java 开发者
|
API 开发工具 Android开发
Android Studio:解决AOSP自编译framework.jar引用不到的问题
在Android Studio中解决AOSP自编译framework.jar引用问题的几种方法,包括使用相对路径、绝对路径和通过`${project.rootDir}`动态获取路径的方法,以避免硬编码路径带来的配置问题。
1398 0
Android Studio:解决AOSP自编译framework.jar引用不到的问题
|
12月前
|
API 开发工具 数据库
开发一份API接口,需要注意这些,看你做到了几项
本文介绍了设计API接口时需注意的关键点,包括数字签名、敏感数据加密与脱敏、限流、参数校验、统一返回与异常处理、请求日志记录、幂等设计、数据量限制、异步处理、参数定义、完整文档及开发者对接SDK等内容,旨在帮助开发者设计出安全、稳定、易维护的API接口。
411 6
开发一份API接口,需要注意这些,看你做到了几项
|
XML Java 开发工具
AAPT2简介
AAPT2简介