Android animate drop down/up view proper

So I ended up doing it myself with some help from this answer.
If it had been Android 3.0, I could have used property animation, but it’s not so I had to do that myself.

Here is what I ended up with:

import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;

/**
 * Class for handling collapse and expand animations.
 * @author Esben Gaarsmand
 *
 */
public class ExpandCollapseAnimation extends Animation {
    private View mAnimatedView;
    private int mEndHeight;
    private int mType;

    /**
     * Initializes expand collapse animation, has two types, collapse (1) and expand (0).
     * @param view The view to animate
     * @param duration
     * @param type The type of animation: 0 will expand from gone and 0 size to visible and layout size defined in XML. 
     * 1 will collapse view and set to gone
     */
    public ExpandCollapseAnimation(View view, int duration, int type) {
        setDuration(duration);
        mAnimatedView = view;
        mEndHeight = mAnimatedView.getLayoutParams().height;
        mType = type;
        if(mType == 0) {
            mAnimatedView.getLayoutParams().height = 0;
            mAnimatedView.setVisibility(View.VISIBLE);
        }
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
        if (interpolatedTime < 1.0f) {
            if(mType == 0) {
                mAnimatedView.getLayoutParams().height = (int) (mEndHeight * interpolatedTime);
            } else {
                mAnimatedView.getLayoutParams().height = mEndHeight - (int) (mEndHeight * interpolatedTime);
            }
            mAnimatedView.requestLayout();
        } else {
            if(mType == 0) {
                mAnimatedView.getLayoutParams().height = mEndHeight;
                mAnimatedView.requestLayout();
            } else {
                mAnimatedView.getLayoutParams().height = 0;
                mAnimatedView.setVisibility(View.GONE);
                mAnimatedView.requestLayout();
                mAnimatedView.getLayoutParams().height = mEndHeight;
            }
        }
    }
}

Example ussage:

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class AnimationTestActivity extends Activity {
    private boolean mActive = false;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        final Button animatedButton = (Button) findViewById(R.id.animatedButton);
        
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                ExpandCollapseAnimation animation = null;
                if(mActive) {
                    animation = new ExpandCollapseAnimation(animatedButton, 1000, 1);
                    mActive = false;
                } else {
                    animation = new ExpandCollapseAnimation(animatedButton, 1000, 0);
                    mActive = true;
                }
                animatedButton.startAnimation(animation);
            }
        });
    }
}

XML:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <Button
        android:id="@+id/animatedButton"
        android:visibility="gone"
        android:layout_width="fill_parent"
        android:layout_height="50dp"
        android:text="@string/hello"/>
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <Button
        android:id="@+id/button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello"/>
</LinearLayout>

Edit

Measure wrap_content height:

So in order to get this to work for wrap_content, I measured the height of the view before I start the animation and then use this measured height as the actual height. Below is the code for measuring the height of the view and set this as the new height (I assume the view uses screen width, change according to your own needs):

/**
 * This method can be used to calculate the height and set it for views with wrap_content as height. 
 * This should be done before ExpandCollapseAnimation is created.
 * @param activity
 * @param view
 */
public static void setHeightForWrapContent(Activity activity, View view) {
    DisplayMetrics metrics = new DisplayMetrics();
    activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

    int screenWidth = metrics.widthPixels;
    
    int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    int widthMeasureSpec = MeasureSpec.makeMeasureSpec(screenWidth, MeasureSpec.EXACTLY);

    view.measure(widthMeasureSpec, heightMeasureSpec);
    int height = view.getMeasuredHeight();
    view.getLayoutParams().height = height;
}

Leave a Comment