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:
width="420" height="315" src="http://www.youtube.com/embed/Xtd88n9N-eo?wmode=opaque" frameborder="0" allowfullscreen="" style="max-width: 100%; display: inline-block; color: rgb(51, 51, 51); font-family: 'Helvetica Neue Light', HelveticaNeue-Light, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 19.6000003814697px; text-align: justify;">
The code is very simple:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
| xmlns:tools="http://schemas.android.com/tools" |
| android:id="@+id/container" |
| android:layout_width="match_parent" |
| android:layout_height="match_parent" |
|
|
| android:orientation="vertical" > |
|
|
| <LinearLayout |
| android:id="@+id/header" |
| android:layout_width="fill_parent" |
| android:layout_height="64dp" |
| android:layout_marginTop="15dp" |
| android:layout_marginLeft="15dp" |
| android:layout_marginRight="15dp" |
| android:background="#FFF" |
| android:orientation="horizontal" > |
|
|
| <TextView |
| android:layout_marginTop="8dp" |
| android:layout_marginLeft="8dp" |
| android:layout_marginBottom="8dp" |
| android:id="@+id/color" |
| android:layout_width="@dimen/color_width" |
| android:layout_height="@dimen/color_height" |
| android:background="@drawable/rectangle" |
| android:gravity="center_vertical" |
| android:text="" |
| android:textAlignment="center" |
| android:textStyle="bold" |
| android:fontFamily="sans-serif-light" |
| /> |
|
|
| <TextView |
| android:id="@+id/clickme" |
| android:layout_width="wrap_content" |
| android:layout_height="wrap_content" |
| android:layout_marginLeft="5dp" |
| android:textStyle="bold" |
| android:gravity="center_vertical" |
| android:fontFamily="sans-serif-light" |
| android:text="@string/clickme" /> |
| </LinearLayout> |
|
|
| <LinearLayout |
| android:id="@+id/expandable" |
| android:layout_width="match_parent" |
| android:layout_height="wrap_content" |
| android:layout_marginLeft="15dp" |
| android:layout_marginRight="15dp" |
| android:background="#FFF" |
| android:orientation="vertical" > |
|
|
| <TextView |
| android:layout_width="wrap_content" |
| android:layout_height="wrap_content" |
| android:fontFamily="sans-serif-light" |
| android:text="@string/hello_world" /> |
|
|
| <TextView |
| android:layout_width="wrap_content" |
| android:layout_height="wrap_content" |
| android:fontFamily="sans-serif-light" |
| android:text="@string/hello_world" /> |
|
|
| <TextView |
| android:layout_width="wrap_content" |
| android:layout_height="wrap_content" |
| android:fontFamily="sans-serif-light" |
| android:text="@string/hello_world" /> |
|
|
| <TextView |
| android:layout_width="wrap_content" |
| android:layout_height="wrap_content" |
| android:fontFamily="sans-serif-light" |
| android:text="@string/hello_world" /> |
|
|
| <TextView |
| android:layout_width="wrap_content" |
| android:layout_height="wrap_content" |
| android:fontFamily="sans-serif-light" |
| android:text="@string/hello_world" /> |
|
|
| </LinearLayout> |
|
|
| </LinearLayout> |
package it.gmariotti.android.examples.animationtest; | |
|
|
| import android.animation.Animator; |
| import android.animation.ValueAnimator; |
| import android.app.Activity; |
| import android.os.Bundle; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.ViewTreeObserver; |
| import android.widget.LinearLayout; |
|
|
| public class MainActivity extends Activity { |
|
|
| LinearLayout mLinearLayout; |
| LinearLayout mLinearLayoutHeader; |
| ValueAnimator mAnimator; |
|
|
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.activity_main); |
|
|
| mLinearLayout = (LinearLayout) findViewById(R.id.expandable); |
| //mLinearLayout.setVisibility(View.GONE); |
| mLinearLayoutHeader = (LinearLayout) findViewById(R.id.header); |
|
|
| //Add onPreDrawListener |
| mLinearLayout.getViewTreeObserver().addOnPreDrawListener( |
| new ViewTreeObserver.OnPreDrawListener() { |
|
|
| @Override |
| public boolean onPreDraw() { |
| mLinearLayout.getViewTreeObserver().removeOnPreDrawListener(this); |
| mLinearLayout.setVisibility(View.GONE); |
|
|
| final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); |
| final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); |
| mLinearLayout.measure(widthSpec, heightSpec); |
|
|
| mAnimator = slideAnimator(0, mLinearLayout.getMeasuredHeight()); |
| return true; |
| } |
| }); |
|
|
|
|
| mLinearLayoutHeader.setOnClickListener(new View.OnClickListener() { |
|
|
| @Override |
| public void onClick(View v) { |
| if (mLinearLayout.getVisibility()==View.GONE){ |
| expand(); |
| }else{ |
| collapse(); |
| } |
| } |
| }); |
| } |
|
|
|
|
| private void expand() { |
| //set Visible |
| mLinearLayout.setVisibility(View.VISIBLE); |
|
|
| /* Remove and used in preDrawListener |
| final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); |
| final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); |
| mLinearLayout.measure(widthSpec, heightSpec); |
|
|
| mAnimator = slideAnimator(0, mLinearLayout.getMeasuredHeight()); |
| */ |
|
|
| mAnimator.start(); |
| } |
|
|
| 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); |
| } |
|
|
| @Override |
| public void onAnimationStart(Animator animator) { |
| } |
|
|
| @Override |
| public void onAnimationCancel(Animator animator) { |
| } |
|
|
| @Override |
| public void onAnimationRepeat(Animator animator) { |
| } |
| }); |
| mAnimator.start(); |
| } |
|
|
|
|
| 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; |
| } |
|
|
|
|
| } |