对于补间动画原理,我们直接查看系统动画源码(部分):
1,AlphaAnimation
/**
* Changes the alpha property of the supplied {@link Transformation}
*/
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float alpha = mFromAlpha;
t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
}
2,TranslateAnimation
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float dx = mFromXDelta;
float dy = mFromYDelta;
if (mFromXDelta != mToXDelta) {
dx = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime);
}
if (mFromYDelta != mToYDelta) {
dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime);
}
t.getMatrix().setTranslate(dx, dy);
}
3,ScaleAnimation
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float sx = 1.0f;
float sy = 1.0f;
float scale = getScaleFactor();
if (mFromX != 1.0f || mToX != 1.0f) {
sx = mFromX + ((mToX - mFromX) * interpolatedTime);
}
if (mFromY != 1.0f || mToY != 1.0f) {
sy = mFromY + ((mToY - mFromY) * interpolatedTime);
}
if (mPivotX == 0 && mPivotY == 0) {
t.getMatrix().setScale(sx, sy);
} else {
t.getMatrix().setScale(sx, sy, scale * mPivotX, scale * mPivotY);
}
}
4,RotateAnimation
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float degrees = mFromDegrees + ((mToDegrees - mFromDegrees) * interpolatedTime);
float scale = getScaleFactor();
if (mPivotX == 0.0f && mPivotY == 0.0f) {
t.getMatrix().setRotate(degrees);
} else {
t.getMatrix().setRotate(degrees, mPivotX * scale, mPivotY * scale);
}
}
由上可以看到,自定义动画的核心思想: 重写applyTransformation方法,通过t 获取变换矩阵matrix ,使用matrix 对目标对象进行相应的变换.(除透明度动画)
以下是几个自定义动画:
1,左右摇动动画
package com.wytiger.customanimation.animation;
import android.view.animation.Animation;
import android.view.animation.Transformation;
/**
* 左右摇动动画
* @author wytiger
* @date 2016年3月16日
*/
public class ShakeAnimation extends Animation {
/**
* 初始化,可以获取到目标控件及父控件的宽高
*/
@Override
public void initialize(int width, int height, int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
}
/**
* 具体要执行的动画效果
* interpolatedTime: 插值时间,也就是执行的百分比
* t: 动画的目标对象
*/
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
// t.setAlpha(interpolatedTime);
//获取变换矩阵,通过变换矩阵设置目标对象平移
t.getMatrix().setTranslate((float) (Math.sin(interpolatedTime*10)*100), 0);
}
}
2,电视机关机动画
package com.wytiger.customanimation.animation;
import android.graphics.Matrix;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;
/**
* 电视剧关闭动画
*
* @author wytiger
* @date 2016年3月16日
*/
public class TVOffAnimation extends Animation {
private int halfWidth;
private int halfHeight;
@Override
public void initialize(int width, int height, int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
setDuration(500);
setFillAfter(true);
// 保存View的中心点
halfWidth = width / 2;
halfHeight = height / 2;
setInterpolator(new AccelerateDecelerateInterpolator());
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
/**
* 横向来讲前80%的时间我们要横向拉伸到150%,纵向是直接减小,最后只留一条线。
* 后20%的时间里我们要横向从150%压缩至0%,纵向保持不变就好了,当横向为0的时候就全部消失了。
* 可能大家对于1+0.625f*interpolatedTime, 1-interpolatedTime/0.8f+0.01f,
* 7.5f*(1-interpolatedTime), 0.01f
* 这4个值比较疑惑,其实很简单,这是一个一次函数的函数值, 如图为sx的变化曲线
*/
final Matrix matrix = t.getMatrix();
if (interpolatedTime < 0.8) {
matrix.preScale(1 + 0.625f * interpolatedTime,
1 - interpolatedTime / 0.8f + 0.01f, halfWidth, halfHeight);
} else {
matrix.preScale(7.5f * (1 - interpolatedTime), 0.01f, halfWidth,
halfHeight);
}
}
}
3,自定义图片旋转动画
package com.wytiger.customanimation.animation;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.view.animation.Animation;
import android.view.animation.Transformation;
/**
* 自定义图片旋转动画
*
* @author wytiger
* @date 2016年3月16日
*/
public class ViewRotateAnimation extends Animation {
int mCenterX;
int mCenterY;
/**
* Camera就像一个摄像机,一个物体在原地不动,然后我们带着这个摄像机四处移动,
* 在摄像机里面呈现出来的画面,就会有立体感,就可以从各个角度观看这个物体。
*/
Camera camera = new Camera();
public ViewRotateAnimation() {
}
@Override
public void initialize(int width, int height,
int parentWidth,int parentHeight){
super.initialize(width, height, parentWidth, parentHeight);
mCenterX = width / 2;
mCenterY = height / 2;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t){
final Matrix matrix = t.getMatrix();
//保存状态,类似于canvas的save方法
camera.save();
//变换
camera.translate(0.0f, 0.0f, (1300 - 1300.0f * interpolatedTime));
camera.rotateY(360 * interpolatedTime);
camera.getMatrix(matrix);
matrix.preTranslate(-mCenterX, -mCenterY);
matrix.postTranslate(mCenterX, mCenterY);
//恢复状态
camera.restore();
}
}