近日有看到QQ点赞的动画效果,于是模仿写了一个
要实现图中效果,需要用到属性动画,属性动画利用ValueAnimator来跟踪记录对象属性已经变化了多长时间及当前这个时间点的值。
如果不设置的话,动画的时长就是300毫秒,每个画面显示的时间是10ms,TypeEvaluator可根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值,自定义TypeEvalutor也很简单,只需要实现evaluate
下面直接贴代码:
activity_main:
<?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" >
<RelativeLayout
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:background="#22B2D6" >
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/ll"
android:layout_alignLeft="@+id/ll"
android:background="@drawable/good" />
<LinearLayout
android:id="@+id/ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="30dip"
android:layout_marginRight="30dip"
android:background="@drawable/ll_bg"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="8dip"
android:background="@drawable/test" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginRight="8dip"
android:gravity="center"
android:text="2555"
android:textColor="#ffffff" />
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:background="#ffffff"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:text="账号信息" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#dddddd" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:text="专享特权" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#dddddd" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:text="QQ空间" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#dddddd" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:text="名片" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#dddddd" />
</LinearLayout>
</LinearLayout>
MainActivity:
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.PointF;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MainActivity extends Activity implements OnClickListener {
private LinearLayout ll;
private ImageView iv;
private ValueAnimator valueAnimator;
private int width, height;
@SuppressLint("NewApi")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll = (LinearLayout) findViewById(R.id.ll);
ll.getBackground().setAlpha(200);
ll.setOnClickListener(this);
iv = (ImageView) findViewById(R.id.iv);
iv.getBackground().setAlpha(0);
}
@SuppressLint("NewApi")
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.ll:
move();
break;
}
}
@SuppressLint("NewApi")
private void move() {
iv.getBackground().setAlpha(255);
width = ll.getRight();
height = ll.getBottom();
valueAnimator = ValueAnimator.ofObject(new MyTypeEvaluator(),
new PointF(iv.getLeft(), iv.getBottom() - iv.getHeight()),
new PointF(width, 0));
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF pointF = (PointF) animation.getAnimatedValue();
iv.setX(pointF.x);
iv.setY(pointF.y);
if ((Math.round(pointF.y)) < 150) {
iv.getBackground().setAlpha(Math.round(pointF.y));
}
}
});
valueAnimator.setTarget(iv);
valueAnimator.setRepeatCount(0);
valueAnimator.start();
}
@SuppressLint("NewApi")
class MyTypeEvaluator implements TypeEvaluator<PointF> {
@Override
public PointF evaluate(float fraction, PointF startValue,
PointF endValue) {
float oneMinusT = 1.0f - fraction;
PointF point = new PointF();
PointF point0 = (PointF) startValue;
PointF point2 = new PointF();
point2.set(0, height);
PointF point3 = (PointF) endValue;
point.x = oneMinusT * oneMinusT * oneMinusT * (point0.x) + 4
* oneMinusT * oneMinusT * fraction * (point0.x) + 2
* oneMinusT * fraction * fraction * (point0.x) + fraction
* fraction * fraction * (point0.x);
point.y = oneMinusT * oneMinusT * oneMinusT * (point0.y)
+ oneMinusT * oneMinusT * fraction * (point0.y) + 2
* oneMinusT * fraction * fraction * (point2.y) + fraction
* fraction * fraction * (point3.y);
return point;
}
}
}
Demo: http://download.csdn.net/detail/qq_18612815/9528559