Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
MoJieBlog opened this issue Aug 28, 2019 · 8 comments
Open

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

MoJieBlog opened this issue Aug 28, 2019 · 8 comments

Comments

@MoJieBlog
Copy link
Collaborator

No description provided.

@DaveBoy
Copy link

DaveBoy commented Aug 28, 2019

view.post一个就行了 一把梭

@zhaoerlei1989
Copy link

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

@uarenothingx
Copy link

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

@gabyallen
Copy link

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

@huazidev
Copy link

huazidev commented May 30, 2020

先说下问题的考点:

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

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

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

@liyanfei250
Copy link

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);
        }
    });
}

@mlinqirong
Copy link

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

@yline
Copy link

yline commented Sep 2, 2023

看了上方的回答,发现“答不对题”;题目是:获取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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants