Android 获取 View 宽高

01.获取View宽高的方式

1.1 onWindowFocusChanged

  • 如下所示

    1
    2
    3
    4
    5
    6
    7
    8
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
    int width = view.getMeasuredWidth();
    int height = view.getMeasuredHeight();
    }
    }

1.2 view.post(runnable)

  • 如下所示

    1
    2
    3
    4
    5
    6
    7
    view.post(new Runnable() {
    @Override
    public void run() {
    int width = view.getMeasuredWidth();
    int height = view.getMeasuredHeight();
    }
    });

1.3 ViewTreeObserver

  • 如下所示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ViewTreeObserver observer = view.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
    view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    int width = view.getMeasuredWidth();
    int height = view.getMeasuredHeight();
    }
    });

1.4 手动测量控件宽高

  • 如下所示

    1
    2
    3
    4
    5
    int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
    int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    imageView.measure(w, h);
    int height = imageView.getMeasuredHeight();
    int width = imageView.getMeasuredWidth();

02.onWindowFocusChanged

  • 该方法的含义是:View已经初始化完毕了,宽/高已经准备好了,所以此时去获取宽/高是没有问题的。
    • 注意:onWindowFocusChanged会被调用多次,当activity的窗口得到焦点和失去焦点时均会被调用一次
    • 具体来说,当activity继续执行(onResume)和暂停执行(onPause)时,onWindowFocusChanged均会被调用。

03.view.post(runnable)

  • 通过post可以将一个runnable投递到消息队列的尾部,然后等待Looper调用此runnable时,View也已经初始化好了。

04.ViewTreeObserver

  • 使用ViewTreeObserver的众多回调也可以完成这个功能,比如使用OnGlobalLayoutListener这个接口。当View树的状态发生改变或者View树内部的View的可见性发生改变时,onGlobalLayout方法将被调用。
    • 注意:伴随着View树的状态改变等,onGlobalLayout会被调用多次。因此需要在适当时机将监听回调移除。

05.手动测量控件宽高

  • 比其他的方法多调用了一次onMeasure()方法,该方法虽然看上去简单,但是如果要目标控件计算耗时比较大的话(如listView等),不建议使用
  • 如果是简单的button,textView等控件,用该方法也可以