getWidth()和getHeight()始终返回0.自定义视图

时间:2013-06-04 18:49:57

标签: android android-view

在片段中,我正在使用多个子视图对布局进行充气。我需要获得其中一个的尺寸(宽度和高度),这是一个自定义视图。

在自定义视图类中,我可以轻松完成。但是如果我尝试从片段中做到这一点,我总是得到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支持。

任何帮助?

7 个答案:

答案 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.OnGlobalLayoutListenerView.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实际上已经进行了一次布局传递。