2019-08-28:谈一谈获取View宽高的几种方法?
MoJieBlog opened this issue · 8 comments
MoJieBlog commented
2019-08-28:谈一谈获取View宽高的几种方法?
DaveBoy commented
view.post一个就行了 一把梭
zhaoerlei1989 commented
1.OnGlobalLayoutListener获取
2.OnPreDrawListener获取
3.OnLayoutChangeListener获取
4.重写View的onSizeChanged()
5.使用View.post()方法
uarenothingx commented
使用MessageQueue.addIdleHandler()也可以获取,而且可以防止多次调用。
gabyallen commented
使用View.post()方法
Context.runOnUiThread(new Runnable()
OnGlobalLayoutListener获取
OnPreDrawListener获取
OnLayoutChangeListener获取
重写View的onSizeChanged()
huazidev commented
先说下问题的考点:
首先,在 view 测量过后就可以获得 view 的测量宽高,另外系统可能需要多次 measure 才能确定最终的测量宽高。
其次,由于 view 的测量过程和 Activity 的生命周期不是同步,所以无法保证在 onCreate,onStart, onResume 时已经测量完毕,如果没有测量完毕获取的宽高都是0。
能获取真实 view 宽高的方法:
- Activity/View 的 onWindowFocusChanged 方法: 方法含义是 View 已经初始完毕,宽高已经准备好了, 得到焦点和失去焦点会被多次调用
- view.post:将 Runnable 投递到消息队列的尾部,当执行到的时候,view 已经初始化好了
- ViewTreeObserver: 使用 ViewTreeObserver 众多回调可以完成这功能,比如 onGlobalLayoutListener,会调用多次
- view.addOnLayoutChangeListener
liyanfei250 commented
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 commented
通过view.post Runnable方法里面通过view.getHeight
yline commented
看了上方的回答,发现“答不对题”;题目是:获取View宽高的几种方法;回答应该是获取方法,而上文回答的全是”获取时机“
- 获取时机:上文都说过了。而且都是能获取到的时机。其实获取不到的时候,判断一下,等有的时候,再存内存里面就可以了。
- 获取方法:
a. getWidth() 和 getHeight() 方法,本质上是等view宽高计算结束,取内存的值。
b. getMeasureWidth 和 getMeasureHeight 方法,本质上是measure结束,取内存的值。
c. View 的宽高本身是可以写死的。那么就可以直接 取值。任何时机结果都是对的。【例如铺满横屏,有时候可以取屏幕宽度】
d. 取业务缓存。这个依据特定场景,例如:同一个手机,上下滑动直播间,共用的同一个Activity,那么界面的高度,是可以复用的。即:第一次获取完成之后,就可以一直用这个高度值。