如果我在onResume中调用布局的getMeasuredWidth()或getWidth()方法,它们会返回0。

41
在onResume中调用getMeasuredWidth()或getWidth()方法返回0。我认为此时视图尚未绘制。
同时,我认为需要将getMeasuredWidth()或getWidth()方法放入布局绘制完成并且视图测量已知的回调方法中。应该使用哪个Android回调方法?
7个回答

79

在系统渲染视图之前(通常是在onCreate/onResume中), 无法使用width/height/getMeasuredWidth/getMeasuredHeight属性获取View的值。

一个简单的解决方法是将Runnable发布到布局中。当View被布置后,该Runnable将被执行。

BoxesLayout = (RelativeLayout) findViewById(R.id.BoxesLinearLayout);
BoxesLayout.post(new Runnable() {
    @Override
    public void run() {
        int w = BoxesLayout.getMeasuredWidth();
        int h = BoxesLayout.getMeasuredHeight();

        ...
    }
});

8
我一直使用ViewTreeObserver这种方法,但这种方式简单多了! - JohnnyLambada
比ViewTreeObserver方法好得多 - Ron
2
非常感谢。运行得很好。 - bashan
16
ViewTreeObserver是更好的方法,因为你可以在视图层次结构绘制到屏幕之前获取宽度/高度的测量值。如果你使用像这样的.post()方法,视图可能会先绘制一帧,然后才会调用你的回调函数。如果你在Runnable内部修改某些视图的宽度/高度,你可能会看到快速闪烁的变化。通过ViewTreeObserver,你可以确保在屏幕绘制第一帧之前修改任何你想要的内容。但是,如果你在Runnable内部没有修改任何视图,则两种方法都应该能正常工作。 - Bitcoin Cash - ADA enthusiast
非常有帮助,谢谢 :) - sharma_kunal
显示剩余2条评论

38

这个答案说:

使用 ViewTreeObserver 监听 View,等待第一次布局完成。只有在第一次布局完成后,getWidth()/getHeight()/getMeasuredWidth()/getMeasuredHeight() 才能正常工作。

ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
  viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
      view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      viewWidth = mediaGallery.getWidth();
      viewHeight = mediaGallery.getHeight();
    }
  });
}

2
我很惊讶地发现,钩入任何生命周期回调都无法获取宽度。我尝试了所有的回调函数,包括onCreate()、onStart()和onResume(),但布局的宽度在这些回调函数中都没有被设置。这个解决方案是我第一个成功的尝试。感谢您的发布。 - John Kroetch
1
哦,removeGlobalOnLayoutListener现在已经被弃用了。API建议使用removeOnGlobalLayoutListener代替(http://developer.android.com/reference/android/view/ViewTreeObserver.html),适用于目标API 16及更高版本。 - John Kroetch

5

您可以在视图中覆盖onLayout()方法以定位每个子视图的位置,因此您可以在调用super(..)之后在那里执行想要执行的操作。


4

实际上,如果布局没有显示在屏幕上,getWidth()方法返回0。对我而言有效的方法是在调用getMeasuredWidth()或getMeasuredHeight()之前调用measure()方法。对于measure方法,我使用了Layout.WRAP_CONTENT参数来获取布局包含内容的测量值。

希望这可以帮到你, Mihai


3

1

解决方案 #1: 要实现动态方式,您需要使用标签。 标签基本上是视图拥有记忆的一种方式。 因此,请将convertView保存在另一个类(MyTag)中。 因此,在您的Java文件内:

private LayoutInflater layoutInflater;

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    MyTag holder = null;
    View row = convertView;
    if (row == null) {
      //Inflate the view however u can  
String strInflater = Context.LAYOUT_INFLATER_SERVICE;
        layoutInflater = (LayoutInflater) context.getSystemService(strInflater);
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        row = inflater.inflate(layoutResID, parent, false);
               holder = new MyTag();

            holder.itemName = (TextView) row.findViewById(R.id.example_itemname);
            holder.icon = (ImageView) row.findViewById(R.id.example_image);
            holder.button1 = (Button) row.findViewById(R.id.swipe_button1);
            holder.button2 = (Button) row.findViewById(R.id.swipe_button2);
            holder.button3 = (Button) row.findViewById(R.id.swipe_button3);
            row.setTag(holder);
        } else {
            holder = (MyTag) row.getTag();
        }

        holder.itemName.setText(itemdata.getItemName());
        System.out.println("holder.button3.getMeasuredWidth()= "+ holder.button3.getMeasuredWidth());
        System.out.println("holder.button3.getWidth()= "+ holder.button3.getWidth());

return row;
} //End of getView()


static class MyTag {  //It also works if not static

        TextView itemName;
        ImageView icon;
        Button button1;
        Button button2;
        Button button3;
    }

解决方案 #2: 硬编码。预设宽度。 在你的res/values/dimens.xml文件中,包含以下内容:
<dimen name="your_button_width">50dp</dimen>

然后在您的 res/layout/your_layout.xml 文件中,包含以下内容:

        <Button  
         android:layout_width="@dimen/your_button_width"  />

然后在您的Java文件中:

int buttonSize= (int) (context.getResources().getDimension(R.dimen.your_button_width));

0
请使用以下代码:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
   super.onWindowFocusChanged(hasFocus);
   Log.e("WIDTH",""+view.getWidth());
   Log.e("HEIGHT",""+view.getHeight());
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接