• 解决获取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获得。

  • 相关阅读:
    排序方法之冒泡排序
    JAVA浮点数的范围 和精度
    史上最全的SPRING注解
    ETL应用:使用Pro*C写入文件信息入库的方法
    MySQL查询优化器工作原理解析
    php通过Mysqli和PDO连接mysql数据详解
    PHP实现各种经典算法
    http协议的状态码——400,401,403,404,500,502,503,301,302等常见网页错误代码
    程序中使用ajax时,type为put,或者delete时在 IIS上没效果,发生HTTP Error 405.0
    linux定时任务crontab
  • 原文地址:https://www.cnblogs.com/ouyangping/p/7398753.html
Copyright © 2020-2023  润新知