属性动画的核心主要是ObjectAnimator,ValueAnimator这几个对象的使用。下面对各个方法的使用进行介绍。
一.单个动画的使用:
ObjectAnimator
.ofFloat(imageView,"rotationY",0,360)
.setDuration(1000)
.start();
ObjectAnimator
.ofFloat(imageView,"rotationX",0,360)
.setDuration(1000)
.start();
ObjectAnimator
.ofFloat(imageView,"scaleX",1f,1.5f)
.setDuration(1000)
.start();
ObjectAnimator
.ofFloat(imageView,"scaleY",1f,1.5f)
.setDuration(1000)
.start();
ObjectAnimator
.ofFloat(imageView,"translationX",0,100)
.setDuration(1000)
.start();
ObjectAnimator
.ofFloat(imageView,"translationY",0,100)
.setDuration(1000)
.start();
ObjectAnimator
.ofFloat(imageView,"alpha",1,0)
.setDuration(1000)
.start();
int startColor = 0xffff0000;
int endColor = 0xff00ff00;
ObjectAnimator
.ofArgb(textView,"backgroundColor",startColor,endColor)
.setDuration(1000)
.start();
PropertyValuesHolder propertyValuesHolder1 = PropertyValuesHolder.ofFloat( "scaleX", 1f, 1.5f);
PropertyValuesHolder propertyValuesHolder2 = PropertyValuesHolder.ofFloat("scaleY", 1f, 1.5f);
ObjectAnimator.ofPropertyValuesHolder(imageView,propertyValuesHolder1
,propertyValuesHolder2)
.setDuration(3000)
.start();
ObjectAnimator animator1 = ObjectAnimator.ofFloat(imageView,"scaleX",1f,4f,1f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(imageView,"scaleY",1f,4f,1f);
AnimatorSet animSet = new AnimatorSet();
//animSet.play(animator1).with(animator2);//一起执行
animSet.play(animator1).after(animator2);//animator1在animator2执行完后执行
//animSet.play(animator1).before(animator2);//animator1在animator2前执行
//animSet.playTogether(animator1,animator2);////一起执行
animSet.setDuration(2000);
animSet.start();
Path path = new Path();
//这边是一个矩形路径,前4个值是left,top,right,bottom值,最后一个参数表示动画的方向(CW代表顺时针和CCW代表逆时针)。
path.addRect(10,10,300,300,Path.Direction.CW); ObjectAnimator.ofFloat(imageView,"translationX","translationY",path).setDuration(3000).start();
ofFloat(T target, Property property, float... values)
实例:
自定义的CircleView:
public class CircleView extends View {
private Paint paint;
private float radius;
public float getRadius() {
return radius;
}
public void setRadius(float radius) {
this.radius = radius;
public CircleView(Context context) {
super(context);
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircleView(Context context, AttributeSet attrs, int
defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
if (paint == null) {
paint = new Paint();
paint.setColor(getResources().getColor(
android.R.color.holo_red_light));
}
canvas.drawCircle(getWidth()/2, getHeight()/2, radius,
paint);
}
}
动画执行代码:
Property property = new Property(Float.class, "radius") {
@Override
public Float get(CircleView object) {
return object.getRadius();
}
@Override
public void set(CircleView object, Float value) {
object.setRadius(value);
}
};
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(circleView, property, 10f,100f,10f);
objectAnimator.setRepeatCount(10);
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
circleView.invalidate();
}
});
objectAnimator.setDuration(2000);
objectAnimator.start();
xml布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.lt.javatest.animal.AnimalActivity">
<com.lt.javatest.animal.CircleView
android:id="@+id/circleView"
android:layout_centerInParent="true"
android:layout_width="100dp"
android:layout_height="100dp" />
<Button
android:id="@+id/scaleButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/circleView"
android:layout_centerHorizontal="true"
android:text="click" />
RelativeLayout>
ValueAnimator类是我们上面说到的ObjectAnimator的父类,阅读源码,我们可以发现ObjectAnimator动画最终是通过ValueAnimation实现的。下面就来说说ValueAnimator的使用。
ValueAnimator valueAnimator = ValueAnimator.ofFloat(1,100);
valueAnimator.setDuration(1000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
imageView.setTranslationX((Float) animation.getAnimatedValue());
}
});
valueAnimator.start();
PropertyValuesHolder property1 = PropertyValuesHolder.ofFloat("value1", 1,100);
PropertyValuesHolder property2 = PropertyValuesHolder.ofFloat("value2", 100, 200);
ValueAnimator valueAnimator = ValueAnimator
.ofPropertyValuesHolder(property1, property2);
valueAnimator.setDuration(1000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value1 = (float) animation.getAnimatedValue("value1");
float value2 = (float) animation.getAnimatedValue("value2");
imageView.setTranslationX(value1);
imageView.setTranslationY(value2);
}
});
valueAnimator.start();
主要代码:
/**
* 二阶赛贝尔曲线,由三个点确定一条曲线
*/
public void paoWuXian(final int[] startLocation, final int[] endLocation, final View
animalView, final View endView) {
final float[] middle = new float[2];
middle[0] = endLocation[0];//中间点的x,这边也可以取其他值
middle[1] = startLocation[1];//中间点的y,这边也可以取其他值
ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration(1000);
valueAnimator.setObjectValues(new PointF(endLocation[0], endLocation[1]));
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
valueAnimator.setEvaluator(new TypeEvaluator() {
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
PointF point = new PointF();
//这边利用的是二阶贝塞尔曲线公式计算x,y
point.x = (1 - fraction) * (1 - fraction) * startLocation[0]
+ 2 * fraction * (1 - fraction) * middle[0]
+ fraction * fraction * endLocation[0];
point.y = (1 - fraction) * (1 - fraction) * startLocation[1]
+ 2 * fraction * (1 - fraction) * middle[1]
+ fraction * fraction * endLocation[1];
return point;
}
});
valueAnimator.start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF point = (PointF) animation.getAnimatedValue();
animalView.setX(point.x);
animalView.setY(point.y);
}
});
valueAnimator.addListener(new ValueAnimator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
//抛物线动画结束后,进行缩放动画
ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration(400);
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
valueAnimator.setObjectValues(1.0f, 0.8f);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
if (value > 0.9) {
endView.setScaleX(value);
endView.setScaleY(value);
} else {
endView.setScaleX(1.8f - value);
endView.setScaleY(1.8f - value);
}
}
});
valueAnimator.start();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
ValueAnimator其实是一个控制值变化的辅助类,我们设置了变化得起点,终点以及时间,这样ValueAnimator提供了一个值变化的监听接口,这样就可以拿到变化的值,然后设置到View上面,形成动画。我们可以通过setEvaluator(TypeEvaluator value)来计算AnimatedValue的值,实现自定义动画。