android中获取控件宽高的几种方式总结

前言

我们知道, 在ActivityonCreate中通过widthheight方法是通常是无法获取到控件的宽高的

因为控件还未测量完毕

如果想要获取到值, 那么有以下几种方式可选

第一种 获取前调用一次measure方法

示例如下:

1
2
3
4
5
6
7
int width = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
int height = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
view.measure(width, height);
view.getMeasuredWidth(); // 获取宽度
view.getMeasuredHeight(); // 获取高度

第二种 使用ViewTreeObserver. OnPreDrawListener进行绘制前事件监听

示例如下:

1
2
3
4
5
6
7
8
9
10
11
view.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {

@Override
public boolean onPreDraw() {
view.getViewTreeObserver().removeOnPreDrawListener(this);
view.getWidth(); // 获取宽度
view.getHeight(); // 获取高度
return true;
}
});

该方法会被调用多次,因此获取到视图的宽度和高度后要移除该监听事件

第三种 使用ViewTreeObserver. OnGlobalLayoutListener

在布局发生改变或者某个视图的可视状态发生改变时调用该事件

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
view.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {

@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= 16) {
view.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
}
else {
view.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
view.getWidth(); // 获取宽度
view.getHeight(); // 获取高度
}
});

该方法会被多次调用,因此需要在获取到视图的宽度和高度后执行 remove 方法移除该监听事件。

第四种 使用View.OnLayoutChangeListener

在视图的 layout 改变时调用该事件, API>=11才能使用

示例如下:

1
2
3
4
5
6
7
8
9
10
11
view.addOnLayoutChangeListener(
new View.OnLayoutChangeListener() {

@Override
public void onLayoutChange(View v, int l, int t, int r, int b,
int oldL, int oldT, int oldR, int oldB) {
view.removeOnLayoutChangeListener(this);
view.getWidth(); // 获取宽度
view.getHeight(); // 获取高度
}
});

该方法同样会被多次调用,因此需要在获取到视图的宽度和高度后执行 remove 方法移除该监听事件。

第五种 View.post() 方法

方法会在 View 的 measure、layout 等事件完成后触发

示例如下:

1
2
3
4
5
6
7
8
view.post(new Runnable() {

@Override
public void run() {
view.getWidth(); // 获取宽度
view.getHeight(); // 获取高度
}
});

该方法只会执行一次,且逻辑简单,建议使用

第六种 重写 View 的 onSizeChanged 方法

在视图的大小发生改变时调用该方法,会被多次调用,因此获取到宽度和高度后需要考虑禁用掉代码

示例如下:

1
2
3
4
5
6
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);

view.getWidth(); // 获取宽度
view.getHeight(); // 获取高度

该实现方法需要继承 View,且多次被调用,不建议使用

第七种 重写 View 的 onLayout 方法

示例如下:

1
2
3
4
5
6
7
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);

view.getWidth(); // 获取宽度
view.getHeight(); // 获取高度
}

该实现方法需要继承 View,且多次被调用,不建议使用

实际场景

目前有个业务需求, 我需要在addView之后获取到被add子控件的宽高, 此时最好的方法就是使用View.post, 如下:

image-20211126123723329

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

0%