我们都知道Android SDK给我们提供了4种常用的动画效果分别是:
AlphaAnimation:透明度变化动画
RotateAnimation:旋转动画
ScaleAnimation: 缩放动画
TranslateAnimation:位置变化动画
但有时这些动画不能满足我们的要求,所以我们要通过自定义动画的手段来实现我们个性化的动画。
学习自定义动画很简单,我们可以参考上面这些SDK中动画类,看它们是如何实现的。就以RotateAnimation为例:
public class RotateAnimation extends Animation {
private float mFromDegrees;
private float mToDegrees;
private int mPivotXType = ABSOLUTE;
private int mPivotYType = ABSOLUTE;
private float mPivotXValue = 0.0f;
private float mPivotYValue = 0.0f;
private float mPivotX;
private float mPivotY;
public RotateAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
// 省略 初始化变量那些事
}
public RotateAnimation(float fromDegrees, float toDegrees) {
// 省略 初始化变量那些事
}
public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY) {
// 省略 初始化变量那些事
}
public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
int pivotYType, float pivotYValue) {
// 省略 初始化变量那些事
}
private void initializePivotPoint() {
if (mPivotXType == ABSOLUTE) {
mPivotX = mPivotXValue;
}
if (mPivotYType == ABSOLUTE) {
mPivotY = mPivotYValue;
}
}
@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);
}
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth);
mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight);
}
}
从该类代码来看,它无非就是重写了applyTransformation,和initialize两个方法而已,而从方法名和内容可以知道applyTransformation就是最核心的动画实现方法。我们在进一步看看这个方法在父类是怎么定义的,在父类Animation类中找到该方法的定义
/**
* Helper for getTransformation. Subclasses should implement this to apply
* their transforms given an interpolation value. Implementations of this
* method should always replace the specified Transformation or document
* they are doing otherwise.
*
* @param interpolatedTime The value of the normalized time (0.0 to 1.0)
* after it has been run through the interpolation function.
* @param t The Transformation object to fill in with the current
* transforms.
*/
protected void applyTransformation(float interpolatedTime, Transformation t) {
}
通过注释我们明白了(也可以结合调试理解):
在动画执行期间,这个方法会被不断回调
参数interpolatedTime:从方法被第一次回调时的0.0,随着动画的执行不断增长,当动画结束时这个值是1.0
参数t:我们通过变化它来实现动画的动作
我们可以再写一个例子玩一下这个方法
class CustomerAnimation extends Animation {
@Override
protected void applyTransformation(float interpolatedTime,
Transformation t) {
t.setAlpha(interpolatedTime);
}
}
就这么几行代码,我们自己实现了个透明度变化动画。
现在我们该了解的都了解了,可以开始动手做“摇摆”动画了
class CustomerAnimation extends Animation {
private int mWaveTimes=5;//摇摆次数
private int mWaveRange=50;//摇摆幅度
public CustomerAnimation(){
}
public CustomerAnimation(int waveTimes,int waveRange){
mWaveTimes = waveTimes;
mWaveRange = waveRange;
}
@Override
protected void applyTransformation(float interpolatedTime,
Transformation t) {
//运用周期性函数,实现左右摇摆
t.getMatrix().setTranslate((int)(Math.sin(interpolatedTime*Math.PI*mWaveTimes)*mWaveRange),0);
}
}