在片段中,我正在使用多个子视图对布局进行充气。我需要获得其中一个的尺寸(宽度和高度),这是一个自定义视图。
在自定义视图类中,我可以轻松完成。但是如果我尝试从片段中做到这一点,我总是得到0作为维度。
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
View culoide = view.findViewWithTag(DRAW_AREA_TAG);
Log.d("event", "culoide is: "+culoide.getWidth()); // always 0
}
我认为onViewCreated应该是获得它的正确位置,但这种情况发生了。我在super.onViewCreated之前尝试过,在调试中它看起来像'findViewWithTag'找到正确的视图,仅尝试使用api 7 v4支持。
任何帮助?
答案 0 :(得分:41)
您必须等到第一个度量和布局后才能获得getWidth()
和getHeight()
的非零值。您可以使用ViewTreeObserver.OnGlobalLayouListener
public void onViewCreated(final View view, Bundle saved) {
super.onViewCreated(view, saved);
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
// get width and height of the view
}
});
}
答案 1 :(得分:5)
我首选的方法是将OnLayoutChangeListener
添加到您要跟踪自己的视图
CustomView customView = ...
customView.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) {
// Make changes
}
});
如果只想要初始布局,可以删除回调中的监听器。
答案 2 :(得分:2)
您必须等到onSizeChanged()方法被调用,然后才能可靠地确定视图大小。
当此视图的大小发生更改时,将在布局期间调用此方法。 如果您刚刚添加到视图层次结构中,则使用 旧值为0。
答案 3 :(得分:1)
尝试拨打
culoide.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
首先,然后尝试getWidth()
和getHeight()
答案 4 :(得分:1)
使用ViewTreeObserver.OnGlobalLayoutListener
,View.post(Runnable action)
或onWindowFocusChanged()
并不是最佳解决方案。 article(注意:我是本文的作者)对此进行了解释,并提供了一个基于doOnLayout
的{{1}} kotlin扩展名的可行解决方案。如果您希望使用Java,则在本文中有一个指向View.OnLayoutChangeListener
源代码的链接,它非常简单,您也可以在Java中执行类似的操作。
答案 5 :(得分:0)
尝试检入onWindowFocusChanged并且它应该具有有效值:
public void onWindowFocusChanged (boolean hasFocus) { }
我有一个类似的问题,我需要获得一个小部件的宽度和高度,这是我可以保证小部件报告它的正确大小的功能。
答案 6 :(得分:0)
这是一个真正的痛苦,尤其是因为您希望在片段生命周期中使用类似onViewCreated的名称来准备视图。对我来说,fragment view本身是这样的:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
getView()?.let{
it.doOnLayout{// do your UI work here }
}
}
这确保片段getView实际上已经进行了一次布局传递。