Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Expand/collapse animation

Let's say I have a vertical linearLayout with :

[v1] [v2] 

By default v1 has visibily = GONE. I would like to show v1 with an expand animation and push down v2 at the same time.

I tried something like this:

Animation a = new Animation() {     int initialHeight;      @Override     protected void applyTransformation(float interpolatedTime, Transformation t) {         final int newHeight = (int)(initialHeight * interpolatedTime);         v.getLayoutParams().height = newHeight;         v.requestLayout();     }      @Override     public void initialize(int width, int height, int parentWidth, int parentHeight) {         super.initialize(width, height, parentWidth, parentHeight);         initialHeight = height;     }      @Override     public boolean willChangeBounds() {         return true;     } }; 

But with this solution, I have a blink when the animation starts. I think it's caused by v1 displaying full size before the animation is applied.

With javascript, this is one line of jQuery! Any simple way to do this with android?

like image 239
Tom Esterez Avatar asked Feb 09 '11 14:02

Tom Esterez


People also ask

How to expand and collapse a view in Android?

The three constructor parameters are view = the view to be animated (in my case, a webview), targetHeight = the maximum height of the view, and down = a boolean which specifies the direction (true = expanding, false = collapsing).


1 Answers

I see that this question became popular so I post my actual solution. The main advantage is that you don't have to know the expanded height to apply the animation and once the view is expanded, it adapts height if content changes. It works great for me.

public static void expand(final View v) {     int matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec(((View) v.getParent()).getWidth(), View.MeasureSpec.EXACTLY);     int wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);     v.measure(matchParentMeasureSpec, wrapContentMeasureSpec);     final int targetHeight = v.getMeasuredHeight();      // Older versions of android (pre API 21) cancel animations for views with a height of 0.     v.getLayoutParams().height = 1;     v.setVisibility(View.VISIBLE);     Animation a = new Animation()     {         @Override         protected void applyTransformation(float interpolatedTime, Transformation t) {             v.getLayoutParams().height = interpolatedTime == 1                     ? LayoutParams.WRAP_CONTENT                     : (int)(targetHeight * interpolatedTime);             v.requestLayout();         }          @Override         public boolean willChangeBounds() {             return true;         }     };      // Expansion speed of 1dp/ms     a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density));     v.startAnimation(a); }  public static void collapse(final View v) {     final int initialHeight = v.getMeasuredHeight();      Animation a = new Animation()     {         @Override         protected void applyTransformation(float interpolatedTime, Transformation t) {             if(interpolatedTime == 1){                 v.setVisibility(View.GONE);             }else{                 v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);                 v.requestLayout();             }         }          @Override         public boolean willChangeBounds() {             return true;         }     };      // Collapse speed of 1dp/ms     a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));     v.startAnimation(a); } 

As mentioned by @Jefferson in the comments, you can obtain a smoother animation by changing the duration (and hence the speed) of the animation. Currently, it has been set at a speed of 1dp/ms

like image 80
Tom Esterez Avatar answered Sep 20 '22 13:09

Tom Esterez