1、动画分类
- 传统动画(帧动画、补间动画)
- 3.0后的属性动画
2、动画-传统动画
2.1、帧动画
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/gif1" android:duration="100"/>
<item android:drawable="@mipmap/gif2" android:duration="100"/>
<item android:drawable="@mipmap/gif3" android:duration="100"/>
<item android:drawable="@mipmap/gif4" android:duration="100"/>
</animation-list>
2.2、补间动画
①alpha(淡入淡出)
②translate(位移)
③rotate(旋转)
④scale(放大缩小)
实例:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0.8"
android:toAlpha="0" />
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
<scale
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" />
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="1"
android:toYDelta="1" />
</set>
3、属性动画
3.1、出现的原因
传统动画的缺点: a)作用对象只是View(如只想操作视图的颜色属性)
b)没有改变View的属性,只是改变了视觉效果
c)动画效果过于单一
3.2、特点
- 作用对象为任意java对象
- 动画效果不只是4种变换
3.3、工作原理
属性动画有两个非常重要的类:ValueAnimator、ObjectAnimator
他们的关系如图:
相关类:
类名 | 用途 |
ValueAnimator | 属性动画主要的计时器,也计算动画后的属性的值,动画的执行类 |
ObjectAnimator | ValueAnimator的一个子类,允许你设置一个目标对象和对象的属性进行动画,动画的执行类 |
AnimatorSet | 提供组织动画的结构,使它们能相关联得运行,用于控制一组动画的执行 |
AnimatorInflater | 用户加载属性动画的xml文件 |
Evaluators | 属性动画计算器,告诉了属性动画系统如何计算给出属性的值 |
Interpolators | 动画插入器,定义动画的变化率 |
3.4、用法
3.4.1、ValueAnimator
①原理:属性动画的机制是通过不断对值进行操作实现的,而初始值和结束值之间的动画过度就是由ValueAnimator这个类负责计算的,它的内部是使用时间循环的机制。ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等
②方法
ValueAnimator.ofInt() 初始值从整数过度到结束值
ValueAnimator.ofFloat() 初始值从浮点数过度到结束值
ValueAnimator.ofObject() 初始值从对象形式过度到结束值
③实例
一个View 4秒从原先宽度变到200的一个动画
a)代码方式
ValueAnimator valueAnimator = ValueAnimator.ofInt(view.getLayoutParams().width, 200);
valueAnimator.setDuration(4000);
valueAnimator.setStartDelay(500);
// 设置动画延迟播放时间
valueAnimator.setRepeatCount(0);
// 设置动画重复播放次数 = 重放次数+1
valueAnimator.setRepeatMode(ValueAnimator.RESTART);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int currentValue= (Integer) valueAnimator.getAnimatedValue();
view.getLayoutParams().width=currentValue;
view.requestLayout();
}
});
valueAnimator.start();
b)xml方式
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:repeatCount="0"
android:repeatMode="restart"
android:valueFrom="0"
android:valueTo="200"
android:valueType="intType"></animator>
Animator animator = AnimatorInflater.loadAnimator(context, R.animator.set_animation);
// 载入XML动画
animator.setTarget(view);
// 设置动画对象
animator.start();
// 启动动画
④特殊ValueAnimator.ofObject()
1、估值器(TypeEvaluator)
插值器(Interpolator
)决定值的变化模式(匀速、加速)
估值器(TypeEvaluator
)决定值的具体变化数值
2、ValueAnimator.ofFloat()原理
其实是系统内置了一个 FloatEvaluator
估值器,内部实现了初始值与结束值 以浮点型的过渡逻辑
public class FloatEvaluator implements TypeEvaluator {
/**
* 重写evaluate
* @param fraction 表示动画完成度(根据它来计算当前动画的值)
* @param startValue 动画的初始值
* @param endValue 动画的结束值
* @return
*/
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
// 初始值 过渡 到结束值 的算法是:
// 1. 用结束值减去初始值,算出它们之间的差值
// 2. 用上述差值乘以fraction系数
// 3. 再加上初始值,就得到当前动画的值
}
}
3、ValueAnimator.ofObject() 从一个点到另一个点移动实例
public class Point {
private float x;
private float y;
public Point(float x, float y) {
this.x = x;
this.y = y;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
}
public class PointEvaluator implements TypeEvaluator {
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
// 将动画初始值startValue 和 动画结束值endValue 强制类型转换成Point对象
Point startPoint = (Point) startValue;
Point endPoint = (Point) endValue;
float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
// 将计算后的坐标封装到一个新的Point对象中并返回
Point point = new Point(x, y);
return point;
}
}
public class MyView extends View {
// 设置需要用到的变量
public static final float RADIUS = 70f;// 圆的半径 = 70
private Point currentPoint;// 当前点坐标
private Paint mPaint;// 绘图画笔
// 构造方法(初始化画笔)
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// 初始化画笔
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
}
// 复写onDraw()从而实现绘制逻辑
// 绘制逻辑:先在初始点画圆,通过监听当前坐标值(currentPoint)的变化,每次变化都调用onDraw()重新绘制圆,从而实现圆的平移动画效果
@Override
protected void onDraw(Canvas canvas) {
// 如果当前点坐标为空(即第一次)
if (currentPoint == null) {
currentPoint = new Point(RADIUS, RADIUS);
// 创建一个点对象(坐标是(70,70))
// 在该点画一个圆:圆心 = (70,70),半径 = 70
float x = currentPoint.getX();
float y = currentPoint.getY();
canvas.drawCircle(x, y, RADIUS, mPaint);
// 步骤1:创建初始动画时的对象点 & 结束动画时的对象点
Point startPoint = new Point(RADIUS, RADIUS);// 初始点为圆心(70,70)
Point endPoint = new Point(700, 1000);// 结束点为(700,1000)
// 步骤2:创建动画对象 & 设置初始值 和 结束值
ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
// 步骤3:设置动画参数
anim.setDuration(5000);
// 设置动画时长
// 步骤3:通过 值 的更新监听器,将改变的对象手动赋值给当前对象
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentPoint = (Point) animation.getAnimatedValue();
// 将每次变化后的坐标值(估值器PointEvaluator中evaluate()返回的Piont对象值)到当前坐标值对象(currentPoint)
// 从而更新当前坐标值(currentPoint)
// 步骤4:每次赋值后就重新绘制,从而实现动画效果
invalidate();
// 调用invalidate()后,就会刷新View,即才能看到重新绘制的界面,即onDraw()会被重新调用一次
// 所以坐标值每改变一次,就会调用onDraw()一次
}
});
anim.start();
// 启动动画
} else {
// 在该点画一个圆:圆心 = (30,30),半径 = 30
float x = currentPoint.getX();
float y = currentPoint.getY();
canvas.drawCircle(x, y, RADIUS, mPaint);
}
}
}
3.4.2、ObjectAnimator
① ValueAnimator与ObjectAnimator区别
ValueAnimator
类是先改变值,然后 手动赋值 给对象的属性从而实现动画;是 间接对对象属性进行操作;ObjectAnimator
类是先改变值,然后 自动赋值 给对象的属性从而实现动画;是 直接对对象属性进行操作;
② 使用方法
a)代码方式
ObjectAnimator anim = ObjectAnimator.ofFloat(object, property, values);
anim.setDuration(500);// 设置动画运行的时长
anim.setStartDelay(500);// 设置动画延迟播放时间
anim.setRepeatCount(0);// 设置动画重复播放次数 = 重放次数+1
anim.setRepeatMode(ValueAnimator.RESTART);// 设置重复播放动画模式
anim.start();// 启动动画
b)xml方式
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:propertyName="alpha">
</objectAnimator>
③ 实现补间动画四种基本变化(平移、旋转、缩放 、透明度)
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(view, "alpha", 0.8f, 0f);//逐渐透明
ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(view, "scaleX", 1f, 3f);//X轴方向缩放到3倍
ObjectAnimator translateAnim = ObjectAnimator.ofFloat(view, "translationX", view.getTranslationX(), 200,view.getTranslationX());//X轴平移
ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f);//360度旋转