Answers:
您可以将树形观察者添加到布局中。这应该返回正确的宽度和高度。onCreate()
在子视图的布局完成之前调用。因此尚未计算宽度和高度。要获取高度和宽度,请将其放在onCreate()
方法上:
final LinearLayout layout = (LinearLayout) findViewById(R.id.YOUR_VIEW_ID);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener (new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
layout.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
} else {
layout.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
int width = layout.getMeasuredWidth();
int height = layout.getMeasuredHeight();
}
});
view.post(Runnable)
,它更清洁并且做同样的事情。
一个真正简单的方法是简单地调用post()
您的布局。创建视图后,这将在下一步中运行您的代码。
YOUR_LAYOUT.post( new Runnable() {
@Override
public void run() {
int width = YOUR_LAYOUT.getMeasuredWidth();
int height = YOUR_LAYOUT.getMeasuredHeight();
}
});
为了避免不推荐使用的代码和警告,可以使用:
view.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
} else {
view.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
yourFunctionHere();
}
});
Kotlin扩展功能更好
inline fun View.waitForLayout(crossinline yourAction: () -> Unit) {
val vto = viewTreeObserver
vto.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
when {
vto.isAlive -> {
vto.removeOnGlobalLayoutListener(this)
yourAction()
}
else -> viewTreeObserver.removeOnGlobalLayoutListener(this)
}
}
})
}
常用方法的一种替代方法是插入视图的视图。
OnPreDrawListener
显示视图时会多次调用,因此在视图具有有效的测量宽度或高度的情况下,没有特定的迭代。这要求您不断验证(view.getMeasuredWidth() <= 0
)或对检查measuredWidth
大于零的次数设置限制。
也有可能永远不会绘制视图,这可能表明您的代码存在其他问题。
final View view = [ACQUIRE REFERENCE]; // Must be declared final for inner class
ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (view.getMeasuredWidth() > 0) {
view.getViewTreeObserver().removeOnPreDrawListener(this);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
//Do something with width and height here!
}
return true; // Continue with the draw pass, as not to stop it
}
});
How can you tell when a layout has been drawn?
,你是提供在那里你调用一个方法OnPreDrawListener
,并don't stop interrogating that view until it has provided you with a reasonable answer
因此反对你的解决方案应该是显而易见的。
只需在布局或视图上调用post方法即可检查它
view.post( new Runnable() {
@Override
public void run() {
// your layout is now drawn completely , use it here.
}
});
post
只会将可运行对象排队等待运行,这并不能确保视图被测量,甚至绘制得更少。
当onMeasure
被称为视图获取其测量宽度/高度。之后,您可以致电layout.getMeasuredHeight()
。