我们都知道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); } }