解决获取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()方法中都没有办法获取到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获得。
解决获取View的width和Height为0的4种方法的更多相关文章
- 解决在onCreate()过程中获取View的width和Height为0的4种方法
很经常当我们动态创建某些View时,需要通过获取他们的width和height来确定别的view的布局,但是在onCreate()获取view的width和height会得到0.view.getWid ...
- 解决在onCreate()过程中获取View的width和Height为0的方法
最近在看Android底层代码的view绘制原理的时候讲到一个很有意思的事情,也是我几年前刚开始学习Android开发的时候比较纳闷的一个问题,如果你不理解Android的底层绘制,请看我之前一片文章 ...
- iPad中控制器view的width和height
一.iPad中控制器view的width和height 1> 规律 * width 是宽高中最小的那个值 * height 是宽高中最大的那个值 2> 举例(比如窗口根控制器的view,有 ...
- Android查缺补漏(View篇)--在 Activity 的 onCreate() 方法中为什么获取 View 的宽和高为0?
在 Activity 的 onCreate() 方法中为什么获取 View 的宽和高为0 ? @Override protected void onCreate(Bundle savedInstanc ...
- Activity中获取view的高度和宽度为0的原因以及解决方案
在activity中可以调用View.getWidth.View.getHeight().View.getMeasuredWidth() .View.getgetMeasuredHeight()来获得 ...
- 使用wpaint绘图软件时:Uncaught DOMException: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The image argument is a canvas element with a width or height of 0.
使用wpaint绘图软件时:Uncaught DOMException: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': Th ...
- Java 获取*.properties配置文件中的内容 ,常见的两种方法
import java.io.InputStream; import java.util.Enumeration; import java.util.List; import java.util.Pr ...
- C#中实现输入汉字获取其拼音(汉字转拼音)的2种方法
主要介绍了C#中实现输入汉字获取其拼音(汉字转拼音)的2种方法,本文分别给出了使用微软语言包.手动编码实现两种实现方式,需要的朋友可以参考下 本文刚发布时,只写了一个实现方式,使用的是微软的语言包,但 ...
- JS获取客户端IP地址、MAC和主机名七种方法
一.使用JS获取客户端IP的几个方法方法一(只针对IE且客户端的IE允许AcitiveX运行,通过平台:XP,SERVER03,2000).获取客户端IP代码:<HTML><HEAD ...
随机推荐
- MVC View与Controller分离
新建了一个 Separate 解决方案, 如下图 Separate.UI UI层. 引用 Separate.Home Separate.Home 把Home控制器分享到 一个类库中 并引用(Sy ...
- C++程序中调用WebService的实现
前言 因为最近的项目中需要运用到在MFC程序中调用WebService里面集成好了的函数,所以特意花了一天的时间来研究WebService的构建以及如何在MFC的程序中添加Web引用,进而来实现在C+ ...
- 3D图形引擎决定三维产业差异化
从2009年中国3D产业初步兴起开始,短短几年间中国的3D技术得到了飞速的发展,3D打印机.3D投影仪.Web3D.虚拟现实.场景漫游等等产业应用应运而生,设备制造商和内容提供商都开始发挥自主创新的优 ...
- vim的命令
下面是从一个博客里摘抄出来的, 供自己学习使用. 在命令状态下对当前行用== (连按=两次), 或对多行用n==(n是自然数)表示自动缩进从当前行起的下面n行.你可以试试把代码缩进任意打乱再用n= ...
- 【js类库AngularJs】解决angular+springmvc的post提交问题
[js类库AngularJs]解决angular+springmvc的post提交问题 AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀的前 ...
- PHP 解决同一个IP不同端口号session冲突的问题
在项目的开发阶段,我们经常会遇到几个站点共用同一个IP用不同端口号区分的形式!但是,这样很容易导致一个问题,session冲突丢失!即两个站点具有相同的session变量,清除session的时候即全 ...
- ftp错误
ftp 550 检查是否目录,文件确定存在. 服务器列表是要设置unix列表模式.
- 内容导出成word
private void 导出word(string 内容) { string tit = "<html xmlns:v=\"urn:schemas-microsoft-co ...
- HDU 2149 Public Sale 拍卖(巴什博弈)
思路:只要能给对方留下n+1,我就能胜,否则败. #include <iostream> #include <cstdio> using namespace std; int ...
- 洛谷 P1145 约瑟夫
题目描述 n个人站成一圈,从某个人开始数数,每次数到m的人就被杀掉,然后下一个人重新开始数,直到最后只剩一个人.现在有一圈人,k个好人站在一起,k个坏人站在一起.从第一个好人开始数数.你要确定一个最小 ...