Expand and collapse animation

If you search a simple code to expand and collpse a View with an animation you'll find a lot of example. Almost all of the examples extend Animation class.

Instead I would like to use an Animator and its listeners.

Where I come from they say I'm discovering the hot water. I know, but it might be useful to someone.
Here you can see a short video:

The code is very simple:
We'll use two LinearLayout.
   ....
    <!-- Header -->  
    <LinearLayout
        android:id="@+id/header"
        android:layout_width="fill_parent"
        android:layout_height="64dp"
        android:background="#FFF"
        android:orientation="horizontal" >
       
        .....

    </LinearLayout>

    <LinearLayout
        android:id="@+id/expandable"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFF"
        android:orientation="vertical" >

        .....

    </LinearLayout>
In our Activity we simply add a OnClickListener to our Header View.
public class MainActivity extends Activity {

     LinearLayout mLinearLayout;
     LinearLayout mLinearLayoutHeader;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
 
         mLinearLayout = (LinearLayout) findViewById(R.id.expandable);
         //set visibility to GONE
         mLinearLayout.setVisibility(View.GONE);
         mLinearLayoutHeader = (LinearLayout) findViewById(R.id.header);
  
         mLinearLayoutHeader.setOnClickListener(new View.OnClickListener() {
 
             @Override
             public void onClick(View v) {
                 if (mLinearLayout.getVisibility()==View.GONE){
                     expand();
                 }else{
                     collapse();
                 }
             }
         });
}
Now we'll create a ValueAnimator to animate the Layout height from 0 to original height to expand the view and from original height to 0 to collpse the view.
private void expand() {
     //set Visible
     mLinearLayout.setVisibility(View.VISIBLE);
     
     final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
     final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
     mLinearLayout.measure(widthSpec, heightSpec);
     
     ValueAnimator mAnimator = slideAnimator(0, mLinearLayout.getMeasuredHeight());
     mAnimator.start();
}
 
private void collapse() {
     int finalHeight = mLinearLayout.getHeight();

     ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
}

private ValueAnimator slideAnimator(int start, int end) {
  
     ValueAnimator animator = ValueAnimator.ofInt(start, end);
}
The previous code snippets, has no real effect. We need to implement the Animation Listeners.
With a AnimatorUpdateListener we'll modify the height.
private ValueAnimator slideAnimator(int start, int end) {
  
    ValueAnimator animator = ValueAnimator.ofInt(start, end);
  
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
         @Override
         public void onAnimationUpdate(ValueAnimator valueAnimator) {
            //Update Height
            int value = (Integer) valueAnimator.getAnimatedValue();
            ViewGroup.LayoutParams layoutParams = mLinearLayout.getLayoutParams();
            layoutParams.height = value;
            mLinearLayout.setLayoutParams(layoutParams);
         }
    });
    return animator;
}
With this code we obtain our purpose.
The final step is to set the visibility to View.GONE when we collapse the view.
We'll use an AnimatorListener.
private void collapse() {
     int finalHeight = mLinearLayout.getHeight();

     ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
  
     mAnimator.addListener(new Animator.AnimatorListener() {
          @Override
          public void onAnimationEnd(Animator animator) {
             //Height=0, but it set visibility to GONE
              mLinearLayout.setVisibility(View.GONE);
          }
          .....   
     });
     mAnimator.start();
}

You can get code from GitHub:

Comments

  1. How to fix if mLinearLayout.getMeasuredHeight () returns a fixed size all the time, although the form itself changes?

    ReplyDelete
  2. This is an awesome article, thank you for sharing.
    Regards,Animation Studio

    ReplyDelete
  3. Thanks for writing such an interesting post on your blog. I enjoyed reading it very much. This kind of information was previously unavailable. I appreciate you writing this profile today. You can find the scrolling speed optimizer here, if you're a speedy gamer. You can also find a Mouse Button & Scroll Wheel TestTool here.

    ReplyDelete

Post a Comment

Popular posts from this blog

How to centralize the support libraries dependencies in gradle

AntiPattern: freezing a UI with Broadcast Receiver

NotificationListenerService and kitkat