实现原理
下拉展开动画,其实就是下拉view的动态设置高度,属性动画的特性是真正的改变了view的属性,动画结束后不止是UI视觉效果,view也真实的显示在布局中。ValueAnimator添加addUpdateListener可以拿到view高度的改变值,然后动态设置为其高度,就可以实现下拉展开的动画效果。
布局代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00DCFE"
android:gravity="center_vertical"
android:onClick="llClick"
android:orientation="horizontal">
<ImageView
android:id="@+id/app_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:gravity="left"
android:text="Click me"
android:textSize="30sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/hidden_view"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#FFBB33"
android:orientation="horizontal"
android:visibility="gone"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/tv_hidden"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="I Am Hidden"
android:textSize="20sp" />
</LinearLayout>
</LinearLayout>
Activity动画实现
/**
* 下拉展开动画
*/
public class DownActivity extends Activity {
private LinearLayout mHiddenView;
private float mDensity;
private int mHiddenViewMeasuredHeight;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_down);
mHiddenView = (LinearLayout) findViewById(R.id.hidden_view);
//获取view的高度
mHiddenViewMeasuredHeight = getWithAndHight(mHiddenView)[0];
}
public void llClick(View view) {
if (mHiddenView.getVisibility() == View.GONE) {
animOpen(mHiddenView);
} else {
animClose(mHiddenView);
}
}
@SuppressLint("NewApi")
private void animOpen(final View view) {
view.setVisibility(View.VISIBLE);
ValueAnimator va = createDropAnim("open",view, 0, mHiddenViewMeasuredHeight);
va.setDuration(1000);
va.start();
}
@SuppressLint("NewApi")
private void animClose(final View view) {
ValueAnimator va = createDropAnim("close",view, mHiddenViewMeasuredHeight, 0);
va.setDuration(1000);
va.start();
}
@SuppressLint("NewApi")
private ValueAnimator createDropAnim(final String type,final View view, int start, int end) {
ValueAnimator va = ValueAnimator.ofInt(start, end);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (Integer) animation.getAnimatedValue();
//动态设置高度
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = value;
view.setLayoutParams(layoutParams);
//如果是关闭动画,当动画结束时view设置为GONE
if(type.equals("close")){
if(value==0){
view.setVisibility(View.GONE);
}
}
}
});
return va;
}
public int[] getWithAndHight(View view) {
int[] location = new int[2];
int width = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
int height = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
view.measure(width, height);
location[0] = view.getMeasuredHeight();
location[1] = view.getMeasuredWidth();
return location;
}
}