解决在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()方法中都没有办法获取到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

时间: 2024-12-23 20:31:53

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

解决获取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()方法中

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

在activity中可以调用View.getWidth.View.getHeight().View.getMeasuredWidth() .View.getgetMeasuredHeight()来获得某个view的宽度或高度,但是在onCreate().onStrart().onResume()方法中会返回0,这是应为当前activity所代表的界面还没显示出来没有添加到WindowPhone的DecorView上或要获取的view没有被添加到DecorView上或者该View的visibili

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

在 Activity 的 onCreate() 方法中为什么获取 View 的宽和高为0 ? @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_view); myview = ViewUtils.find(this, R.id.myview); getViewSize("onCr

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

整个spring mvc的架构如下图所示: 上篇文件讲解了DispatcherServlet第二步:通过request从Controller获取ModelAndView.现在来讲解第三步:request 从ModelAndView中获取view对象. 获取view对象一般是通过viewResolver来解析view name来完成的.若ModelAndView中view 不存在或者ModelAndView本身为null则填充默认值.代码如下: ModelAndView中view 不存在或者Mod

HackThirteen 在onCreate()方法中获取View的宽度和高度

1.概要: Android源代码中很多模块都使用了post()方法,深入理解框架曾运行机制对于避开类似于本例中的小陷阱是很重要的 2.问题提出: 如果开发一些依赖于UI控件的宽和高的功能,开发者可能会用到View的getHeight()和getWidth()方法.试图在Activity的 onCreate()方法中获取控件的宽和高.遗憾的是如果开发者在onCreate()方法中调用上述方法,会发现返回值都是0. 3.解释问题原因: 当onCreate()方法被调用时,会通过LayoutInfla

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

1. 相对位置: getLeft() , getRight(), getTop(), getBottom() 在Android中可以把left相当于X轴值, top相当于Y轴值, 通过这两个值Android系统可以知道视图的绘制起点,在通过Wdith 和 Height 可以得到视图上下左右具体值,就可以在屏幕上绝对位置绘制视图.right 与 bottom计算如下: right = left + width; bottom = top + height; 视图左侧位置  view.getLeft

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

获取View类界面控件的位置,有助于添加新的控件. 获取在parent里的相对坐标位置   这个比较简单,不用多说,直接调用View的方法:getLeft , getTop, getBottom, getRight获得. 获取在屏幕中的绝对位置 getLocalVisibleRect getGlobalVisibleRect 这个方法是构建一个Rect用来"套"这个view.此Rect的坐标是相对当前activity而言. 若是普通activity,则Rect的top为可见的状态栏高度

安卓图片缩放中java.lang.IllegalArgumentException: width and height must be &gt; 0错误

第一次写博客,都是低级的错误,大神见笑了. 今天做安卓加载图片到 ImageView,报了 一个 java.lang.IllegalArgumentException: width and height must be > 0错误,只能怪我英文不好,没看懂.先把我的代码贴出来. 1 bmp = BitmapFactory.decodeStream(cr.openInputStream(uri)); 2 3 // 缩放图片 4 WindowManager wm = getWindowManager

通过findViewById()方法从layout中获取view并进行相应的转换时提示:&quot;Cannot cast from View to AutoCompleteTextView&quot;的解决办法!(转+自己错误)

转:http://blog.csdn.net/zyz511919766/article/details/7453864 代码: 1 package zyz.example.autocompletetextview; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.widget.ArrayAdapter; 6 7 public class AutoCompleteTextView exten