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; |
|
} |
|
|
|
|
|
} |