Skip to content

2019-08-28:谈一谈获取View宽高的几种方法? #131

Open

Description

@MoJieBlog
No description provided.

Activity

  1. DaveBoy commented on Aug 28, 2019

    @DaveBoy

    view.post一个就行了 一把梭

  2. zhaoerlei1989 commented on Aug 28, 2019

    @zhaoerlei1989

    1.OnGlobalLayoutListener获取
    2.OnPreDrawListener获取
    3.OnLayoutChangeListener获取
    4.重写View的onSizeChanged()
    5.使用View.post()方法

  3. uarenothingx commented on Aug 28, 2019

    @uarenothingx

    使用MessageQueue.addIdleHandler()也可以获取,而且可以防止多次调用。

  4. gabyallen commented on Aug 28, 2019

    @gabyallen

    使用View.post()方法
    Context.runOnUiThread(new Runnable()
    OnGlobalLayoutListener获取
    OnPreDrawListener获取
    OnLayoutChangeListener获取
    重写View的onSizeChanged()

  5. huazidev commented on May 30, 2020

    @huazidev

    先说下问题的考点:

    首先,在 view 测量过后就可以获得 view 的测量宽高,另外系统可能需要多次 measure 才能确定最终的测量宽高。
    其次,由于 view 的测量过程和 Activity 的生命周期不是同步,所以无法保证在 onCreate,onStart, onResume 时已经测量完毕,如果没有测量完毕获取的宽高都是0。

    能获取真实 view 宽高的方法:

    • Activity/View 的 onWindowFocusChanged 方法: 方法含义是 View 已经初始完毕,宽高已经准备好了, 得到焦点和失去焦点会被多次调用
    • view.post:将 Runnable 投递到消息队列的尾部,当执行到的时候,view 已经初始化好了
    • ViewTreeObserver: 使用 ViewTreeObserver 众多回调可以完成这功能,比如 onGlobalLayoutListener,会调用多次
    • view.addOnLayoutChangeListener
  6. liyanfei250 commented on Dec 23, 2020

    @liyanfei250

    1 通过 looper 队列

    /**
     * 通过 looper 队列
     */
    private void getHeight1() {
        tvText.post(new Runnable() {
            @Override
            public void run() {
                int height = tvText.getHeight();
                Log.i(TAG, "MainActivity;getHeight1;height=" + height);
            }
        });
    }
    

    2 当视图树的布局发生改变时

    /**
     * 当视图树的布局发生改变时
     */
    private void getHeight2() {
        tvText.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                tvText.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    
                int height = tvText.getHeight();
                Log.i(TAG, "MainActivity;getHeight2;height=" + height);
            }
        });
    }
    

    3 当视图树的进行绘制时

    /**
     * 当视图树的进行绘制时
     */
    private void getHeight3() {
        tvText.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                tvText.getViewTreeObserver().removeOnPreDrawListener(this);
    
                int height = tvText.getHeight();
                Log.i(TAG, "MainActivity;getHeight3;height=" + height);
                return false;
            }
        });
    }
    

    4 view 布局改变时

    /**
     * view 布局改变时
     */
    private void getHeight4() {
        tvText.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                tvText.removeOnLayoutChangeListener(this);
                int height = tvText.getHeight();
                Log.i(TAG, "MainActivity;getHeight4;height=" + height);
            }
        });
    }
    
  7. mlinqirong commented on Dec 20, 2021

    @mlinqirong

    通过view.post Runnable方法里面通过view.getHeight

  8. yline commented on Sep 2, 2023

    @yline

    看了上方的回答,发现“答不对题”;题目是:获取View宽高的几种方法;回答应该是获取方法,而上文回答的全是”获取时机“

    1. 获取时机:上文都说过了。而且都是能获取到的时机。其实获取不到的时候,判断一下,等有的时候,再存内存里面就可以了。
    2. 获取方法:
      a. getWidth() 和 getHeight() 方法,本质上是等view宽高计算结束,取内存的值。
      b. getMeasureWidth 和 getMeasureHeight 方法,本质上是measure结束,取内存的值。
      c. View 的宽高本身是可以写死的。那么就可以直接 取值。任何时机结果都是对的。【例如铺满横屏,有时候可以取屏幕宽度】
      d. 取业务缓存。这个依据特定场景,例如:同一个手机,上下滑动直播间,共用的同一个Activity,那么界面的高度,是可以复用的。即:第一次获取完成之后,就可以一直用这个高度值。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions