tags:

views:

79

answers:

4

I am trying to apply an animation to a view in my Android app after my activity is created. To do this, I need to determine the current size of the view, and then set up an animation to scale from the current size to the new size. This part must be done at runtime, since the view scales to different sizes depending on input from the user. My layout is defined in XML.

This seems like an easy task, and there are lots of SO questions regarding this though none which solved my problem, obviously. So perhaps I am missing something obvious. I get a handle to my view by:

ImageView myView = (ImageView)getWindow().findViewById(R.id.MyViewID);

This works fine, but when calling getWidth(), getHeight(), getMeasuredWidth(), getLayoutParams().width, etc., they all return 0. I have also tried manually calling measure() on the view followed by a call to getMeasuredWidth(), but that has no effect.

I have tried calling these methods and inspecting the object in the debugger in my activity's onCreate() and in onPostCreate(). How can I figure out the exact dimensions of this view at runtime?

+1  A: 

Are you calling getWidth() before the view is actually laid out on the screen?

A common mistake made by new Android developers is to use the width and height of a view inside its constructor. When a view’s constructor is called, Android doesn’t know yet how big the view will be, so the sizes are set to zero. The real sizes are calculated during the layout stage, which occurs after construction but before anything is drawn. You can use the onSizeChanged( )method to be notified of the values when they are known, or you can use the getWidth( ) and getHeight( )methods later, such as in the onDraw( ) method.

mbaird
So does that mean I need to override ImageView just to catch the `onSizeChange()` event to know the real size? That seems like a bit of overkill... though at this point I'm desperate just to get the code working, so it's worth a shot.
Nik Reiman
I was thinking more of like waiting till your onCreate() has finished in your Activity.
mbaird
As mentioned, I tried putting this code in `onPostCreate()` which gets run after the view is completely created and started.
Nik Reiman
A: 

I have similar situation where I need to generate a new MapView.LayoutParams in order to place a popup balloon on a MapView.

The constructor's signature is MapView.LayoutParams(int width, int height, GeoPoint point, int alignment)

But at the moment where I make the call I do not know the width and height of the popup yet.

yann.debonnel
+2  A: 

Based on @mbaird's advice, I found a workable solution by subclassing the ImageView class and overriding onLayout(). I then created an observer interface which my activity implemented and passed a reference to itself to the class, which allowed it to tell the activity when it was actually finished sizing.

I'm not 100% convinced that this is the best solution (hence my not marking this answer as correct just yet), but it does work and according to the documentation is the first time when one can find the actual size of a view.

Nik Reiman
Good to know. If I find anything that would allow you to get around having to subclass the View I'll post it here. I'm a bit surprised onPostCreate() didn't work.
mbaird
A: 

Here is the code for getting the layout via overriding a view:

public class CustomListView extends ListView
{
    private OnLayoutChangedListener layoutChangedListener;

    public CustomListView(Context context)
    {
        super(context);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        if (layoutChangedListener != null)
        {
            layoutChangedListener.onLayout(changed, l, t, r, b);
        }
        super.onLayout(changed, l, t, r, b);
    }

    public void setLayoutChangedListener(
        OnLayoutChangedListener layoutChangedListener)
    {
        this.layoutChangedListener = layoutChangedListener;
    }
}
public interface OnLayoutChangedListener
{
    void onLayout(boolean changed, int l, int t, int r, int b);
}
gregm