动画完全解析(二):补间动画原理及自定义动画

对于补间动画原理,我们直接查看系统动画源码(部分):

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();
}

}

原文地址:https://www.cnblogs.com/wytiger/p/5284343.html