1.简介
Animation一般动画就是我们前面学的帧动画和补间动画。Animator则是本节要讲的属性动画。
2.图解
3.属性动画之ValueAnimator详解
3.1.使用流程
3.1.1.调用ValueAnimator的ofInt(),ofFloat()或ofObject()静态方法创建ValueAnimator实例。
3.1.2.调用实例的setXxx方法设置动画持续时间,插值方式,重复次数等。
3.1.3.调用实例的addUpdateListener添加AnimatorUpdateListener监听器,在该监听器中 可以获得ValueAnimator计算出来的值,你可以值应用到指定对象上。
3.1.4.调用实例的start()方法开启动画! 另外我们可以看到ofInt和ofFloat都有个这样的参数:float/int... values代表可以多个值。
3.2.代码实现
3.2.1.布局
3.2.2.Java代码
public class AnimationDrawableActivity extends AppCompatActivity {
private Button btn_one;
private Button btn_two;
private Button btn_three;
private Button btn_four;
private LinearLayout linearLayout;
private ImageView imageView;
private int width;
private int height;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animationdrawable);
linearLayout = (LinearLayout) findViewById(R.id.linearlayout);
btn_one = (Button) findViewById(R.id.button1);
btn_two = (Button) findViewById(R.id.button2);
btn_three = (Button) findViewById(R.id.button3);
btn_four = (Button) findViewById(R.id.button4);
imageView = (ImageView) findViewById(R.id.imageview);
btn_one.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
lineAnimator();
}
});
btn_two.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
scaleAnimator();
}
});
btn_three.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
raAnimator();
}
});
btn_four.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
circleAnimator();
}
});
}
/**
* 移动图片
* */
private void moveView(View view, int rawX, int rawY) {
int left = rawX - imageView.getWidth() / 2;
int top = rawY - imageView.getHeight();
int width = left + view.getWidth();
int height = top + view.getHeight();
view.layout(left, top, width, height);
}
//按轨迹方程来运动
private void lineAnimator() {
width = linearLayout.getWidth();
height = linearLayout.getHeight();
ValueAnimator xValue = ValueAnimator.ofInt(height, 0, height / 4, height / 2, height / 4 * 3, height);
xValue.setDuration(3000L);
xValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 轨迹方程 x = width / 2
int y = (Integer) animation.getAnimatedValue();
int x = width / 2;
moveView(imageView, x, y);
}
});
xValue.setInterpolator(new LinearInterpolator());
xValue.start();
}
//缩放效果
private void scaleAnimator() {
ValueAnimator vValue = ValueAnimator.ofFloat(1.0f, 0.6f, 1.2f, 1.0f, 0.6f, 1.2f, 1.0f);
vValue.setDuration(1000L);
vValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float scale = (Float) animation.getAnimatedValue();
imageView.setScaleX(scale);
imageView.setScaleY(scale);
}
});
vValue.setInterpolator(new LinearInterpolator());
vValue.start();
}
//旋转的同时透明度变化
private void raAnimator() {
ValueAnimator rValue = ValueAnimator.ofInt(0, 360);
rValue.setDuration(1000L);
rValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int rotateValue = (Integer) animation.getAnimatedValue();
imageView.setRotation(rotateValue);
float fractionValue = animation.getAnimatedFraction();
imageView.setAlpha(fractionValue);
}
});
rValue.setInterpolator(new DecelerateInterpolator());
rValue.start();
}
//圆形旋转
protected void circleAnimator() {
width = linearLayout.getWidth();
height = linearLayout.getHeight();
final int R = width / 4;
ValueAnimator tValue = ValueAnimator.ofFloat(0, (float) (2.0f * Math.PI));
tValue.setDuration(1000);
tValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 圆的参数方程 x = R * sin(t) y = R * cos(t)
float t = (Float) animation.getAnimatedValue();
int x = (int) (R * Math.sin(t) + width / 2);
int y = (int) (R * Math.cos(t) + height / 2);
moveView(imageView, x, y);
}
});
tValue.setInterpolator(new DecelerateInterpolator());
tValue.start();
}
}
使用的流程非常简单,先创建ValueAnimator对象,调用ValueAnimator.ofInt/ofFloat 获得,然后设置动画持续时间。addUpdateListener添加AnimatorUpdateListener事件监听, 然后使用参数animation的getAnimatedValue()获得当前的值,然后我们可以拿着这个值 来修改View的一些属性,从而形成所谓的动画效果,接着设置setInterpolator动画渲染模式, 最后调用start()开始动画的播放。
4.属性动画之ObjectAnimator详解
4.1.说明
比起ValueAnimator,ObjectAnimator显得更为易用,通过该类我们可以直接对任意对象的任意属性进行动画操作。而不单单只是View对象, 不断地对对象中的某个属性值进行赋值,然后根据对象属性值的改变再来决定如何展现出来。比如为TextView设置如下动画: ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f);
这里就是不断改变alpha的值,从1f - 0f,然后对象根据属性值的变化来刷新界面显示,从而 展现出淡入淡出的效果,而在TextView类中并没有alpha这个属性。
ObjectAnimator内部机制是: 寻找传输的属性名对应的get和set方法,而非找这个属性值。
4.2.代码实现
4.2.1.布局
4.2.2.Java代码
public class AnimationDrawableActivity extends AppCompatActivity {
private Button btn_one;
private Button btn_two;
private Button btn_three;
private Button btn_four;
private Button btn_five;
private LinearLayout linearLayout;
private int height;
private ObjectAnimator animator1;
private ObjectAnimator animator2;
private ObjectAnimator animator3;
private ObjectAnimator animator4;
private AnimatorSet animSet;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animationdrawable);
linearLayout = (LinearLayout) findViewById(R.id.linearlayout);
textView= (TextView) findViewById(R.id.textview);
btn_one = (Button) findViewById(R.id.button1);
btn_two = (Button) findViewById(R.id.button2);
btn_three = (Button) findViewById(R.id.button3);
btn_four = (Button) findViewById(R.id.button4);
btn_five= (Button) findViewById(R.id.button5);
height = linearLayout.getHeight();
initAnimator();
btn_one.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
animator1.setDuration(3000l);
animator1.start();
}
});
btn_two.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
animator2.setDuration(3000l);
animator2.start();
}
});
btn_three.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
animator3.setDuration(3000l);
animator3.start();
}
});
btn_four.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
animator4.setDuration(3000l);
animator4.start();
}
});
btn_five.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//将前面的动画集合到一起
animSet = new AnimatorSet();
animSet.play(animator4).with(animator3).with(animator2).after(animator1);
animSet.setDuration(5000l);
animSet.start();
}
});
}
//初始化动画
private void initAnimator() {
animator1 = ObjectAnimator.ofFloat(textView, "alpha", 1f, 0f, 1f, 0f, 1f);
animator2 = ObjectAnimator.ofFloat(textView, "rotation", 0f, 360f, 0f);
animator3 = ObjectAnimator.ofFloat(textView, "scaleX", 2f, 4f, 1f, 0.5f, 1f);
animator4 = ObjectAnimator.ofFloat(textView, "translationY", height / 8, -100, height / 2);
}
}
5.属性动画之Evaluator详解
5.1.图解
5.2.IntEvaluator的源码
5.3.代码实现
5.3.1.Java Bean类
public class Point {
private float x;
private float y;
public Point() {
}
public Point(float x, float y) {
this.x = x;
this.y = y;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public void setX(float x) {
this.x = x;
}
public void setY(float y) {
this.y = y;
}
}
5.3.2.TypeEvaluator实现类
public class PointEvaluator implements TypeEvaluator {
@Override
public Point evaluate(float fraction, Point startValue, Point endValue) {
float x = startValue.getX() + fraction * (endValue.getX() - startValue.getX());
float y = startValue.getY() + fraction * (endValue.getY() - startValue.getY());
Point point = new Point(x, y);
return point;
}
}
5.3.3.自定义View
public class AnimView extends View {
public static final float RADIUS = 80.0f;
private Point currentPoint;
private Paint mPaint;
public AnimView(Context context) {
this(context, null);
}
public AnimView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public AnimView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
}
private void drawCircle(Canvas canvas){
float x = currentPoint.getX();
float y = currentPoint.getY();
canvas.drawCircle(x, y, RADIUS, mPaint);
}
private void startAnimation() {
Point startPoint = new Point(RADIUS, RADIUS);
Point endPoint = new Point(getWidth() - RADIUS, getHeight() - RADIUS);
ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentPoint = (Point) animation.getAnimatedValue();
invalidate();
}
});
anim.setDuration(3000l);
anim.start();
}
@Override
protected void onDraw(Canvas canvas) {
if (currentPoint == null) {
currentPoint = new Point(RADIUS, RADIUS);
drawCircle(canvas);
startAnimation();
} else {
drawCircle(canvas);
}
}
}
5.3.4.Java代码使用
setContentView(new AnimView(this));
6.Interpolator(补间器)详解
6.1.图解
6.2.Interpolator的内部实现机制
完成代码:https://github.com/wujianning/AndroidAnimation
附1:帧动画讲解:Android 动画之帧动画
附2:补间动画讲解:Android 动画之补间动画