`
iaiai
  • 浏览: 2142312 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

解决在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过程后调用。
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是固定的,那么你可以直接使用:
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
分享到:
评论

相关推荐

    基于Java的Android应用程序开发-24点游戏源码+详细项目说明.zip

    基于Java的Android应用程序开发-24点游戏源码+详细项目说明.zip 基于Java的Android应用程序...layout_width以及layout_height,分别设置view的宽高;gravity指定当文本小于视图时如何通过视图的 x 和/或 y 轴对齐文本

    二维码生成器

    super onCreate savedInstanceState ; setContentView R layout main ; this setTitle &quot;Android条码 二维码识别Demo hellogv&quot; ; imgView ImageView this findViewById R id ImageView01 ; ...

    viewpager相关

    public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub return arg0 == arg1; } @Override public int getCount() { // TODO Auto-generated...

    Android移动开发实验6.doc

    " "(4)创建DetailActivity,并重写它的onCreate()方法和onCreatOptionsM" "enu()方法,并且在onCreated()方法中,添加代码控制导航图标的显示; " "(5)重写onOptionsItemSelected()方法,实现通过调用NavUtils....

    button按钮的四种监听及实例

     在button下加上如下代码android:onClick=skip(skip即为方法对应的名字,然后在java代码中在定义具体的方法)   android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height=...

    MapView的使用

    在论坛里看到一篇 "MapView和其它控件一起显示 " 的帖子, 那是很老的一篇帖子了, 很多朋友都说无法在android SDK 1.0上运行。既然那么多人关心,我在这里就把它重写一遍,顺便加入了一些新的功能 ,感兴趣的朋友可以...

    Android实验5-事件处理答案.doc

    一、实验名称:实验5 事件处理 二、实验日期: 三、实验目的: 基于监听的事件处理 基于回调的事件处理 四、实验用的仪器和材料:Windows+Eclipse+jdk+sdk+adt 五、实验的步骤和方法: 实验一:基于监听的事件处理...

    android顶部滑动导航

    //如果标题是第3个及大于第3个时 获取当前标题左端的x坐标值 否则 为 0 int x1=checkedId &gt; 1 ? ((RadioButton) radioGroup.getChildAt(checkedId)).getLeft() : 0; //获取第2个标题左端的x坐标值 ...

    高仿微信界面

    现在三个Fragment已经添加到了MainActivity中,滑动ViewPager切换Fragment,同时底部的导航栏也会切换,在为ViewPager添加监听以前,先说说底部导航栏。 第二步,底部导航。 这个的切换其实就是切换准备好的png...

    谈谈Android里的Context的使用

    这里大致可以分为两种:一是传递Context参数,二是调用全局的Context. 其实我们应用启动的时候会启动Application这个类,这个类是在AndroidManifest.xml文件里其实是默认的 android:icon="@drawable/ic_...

    LCRapidDevelop-master

    列表部分和上面的一样就不说了,我这边主要描叙视频播放的部分 是在不懂得可以clone到本地仓库跑一边 item_layout.xml ``` android:layout_width="match_parent" android:layout_height="wrap_content" android...

    炫舞吧 android 游戏开发

    private int bitmap_main_4_Height = 0; private MediaPlayer mMediaPlayer = null; private SoundPool mSoundPool = null; private int button_sound = 0; private Bitmap bitmap_up = null; // 屏幕尺寸 ...

    LoadingLayoutDemo-加载中、无网络、无数据、出错4种状态的载入布局.zip

    前言项目里都会遇到几种页面,分别为加载中、无网络、无数据、出错四种情况,经常要使用,所以封成库引用了,方便使用,顺便分享出来。先看一下效果: 原理比较简单,继承FrameLayout,在xml渲染完成后,加上加载中...

    分享一个牛逼的android开发框架,看着好屌的样子

    A、需要绑定注入对象,建议写到Application中的onCreate SNBindInjectManager.instance().bind(ITest.class, Test.class); B、与视图注入不同的是属性必须添加标签@SNIOC,注入的对象(Test)必须包含只有一个...

    应用启动页自定义跳转计时器View Demo

    应用启动页自定义跳转计时器View Demo: CircleTextProgressbar.java: package com.demo.startpageskiptimerdemo.widget; import android.content.Context; import android.content.res.ColorStateList; import ...

    透明与窗体的设置

    在测试中发现,在onCreate()事件中增加setTheme(),必须在setContentView()之前,否则指定的Style不能生效 2.Custom Title Android除了可以为指定的Activity设置显示风格,此外也可以为指定的Activity设置一些特效...

    动态圆弧进度条

    int textHeight = height / 4; paint.setTextSize(textHeight); int textWidth = (int) paint.measureText(text, 0, text.length()); paint.setStyle(Style.FILL); // canvas.drawText(text, width / 2 - ...

    Gif-Load-ReTry-Refresh-支持gif图片的Load反馈框架,只需一张gif图,一行代码解决初次加载,重试加载,刷新加载,与生命周期绑定,LeakCanary检测无内存泄漏.zip

    Activity中使用一致,请在 Toolbar下的需要加载的内容最外层套一层 FrameLayout(为何需要这样做)代码中方法简介方法参数作用registerFragment,View,LoadRetryRefreshListener注册(View为Fragment在onCreateView...

    新版Android开发教程.rar

    � A ndroid 在设计初期就考虑了与现其有业务的融合,改变以往从计算机为主改成从手机使用为导向。新 生应用如:G oogle 地图及其衍生应用、 GMail 、 GTalk 等。 � GPS 卫星导航功能,手机照相, MP3 ,蓝芽等均...

    wkp111_StickLayout-粘性控件,其任意一个子控件都可滑动停留,本质为NestedScrollView和LinearLayout的结合。.zip

    粘性控件,其任意一个子控件都可滑动停留,无论是View,还是ViewGroup;用该控件可以轻松实现支付宝"全部应用"界面。演示图 Note:图1为设置属性wkp_canScrollToEndViewTop=true,图2没有;图3为设置滑动改变监听。...

Global site tag (gtag.js) - Google Analytics