Android 中动画的实现

一、引言
1、Android 中动画有多种, 常用的有两种, 即view动画和属性动画,这两者在视觉效果上并没太大不同, 实现方式也是大同小异, 但有一个显著区别:
例如一个平移动画, 在视觉上都感觉控件已经离开了原来的位置, 但view动画并不改变控件对触摸和点击的响应位置, 控件的响应范围还在控件最初始的位置,点击视觉上的位置并不生效;
但属性动画的响应范围和位置却会随着控件动画的变化而变化。
2、另一个区别一般用不到, 也是在测试时无意发现, 对同一个控件执行不同的动画, view动画会默认清除上一个动画的效果, 但属性动画却会保留上一个动画的效果, 即属性动画连续执行多个动画而不手动清除效果, 就会变成混合动画。
3、Android 中动画设置比较简单, 但不同动画混合的效果千变万化, 项目的工具类 BasisAnimUtils 只是提供给一个参考, 具体应用时最好重新编写。
4、项目地址: https://github.com/GinGod/BasisDependency , 具体参考类:BasisAnimUtils 和 AnimationActivity
二、view动画
1、几个通用方法解释
a. setDuration(long durationMillis)设置单次动画播放时长, 单位是 ms(毫秒)
b. setRepeatCount(int repeatCount)设置动画重复次数, 常用值: Animation.INFINITE (无限次)
c. setRepeatMode(int repeatMode)设置重复模式,常用值: Animation.REVERSE (反转开始), Animation.RESTART(重新开始)
d. setFillAfter(boolean fillAfter)设置动画结束后控件停留的位置,常用值: false (默认)回到原始位置, true 停留在动画停止的最后一帧上

e. setInterpolator(Interpolator i) (不常用)动画执行速率, 常用值:new LinearInterpolator() 匀速(在连续旋转中用到)

2、透明(alpha)动画

/** * 透明度渐变的动画 */ public static void alpha(View view) { AlphaAnimation aa = new AlphaAnimation(1.0f, 0.2f); // 动画播放的时间长度 aa.setDuration(2000); // 设置重复播放的次数 aa.setRepeatCount(Animation.INFINITE); // 设置重复播放的模式 aa.setRepeatMode(Animation.REVERSE); //动画结束后还原到初始状态 aa.setFillAfter(true); // 让iv播放aa动画 view.startAnimation(aa); }

3、平移(translate)动画
Animation.RELATIVE_TO_SELF相对于自己

Animation.RELATIVE_TO_PARENT相对于父窗口
Tip: 相对于父窗口是相对于view的直接父控件, 若控件被某一ViewGroup包裹, 测试发现动画只在父窗口范围内显示, 超出父窗口的位置不显示, 后面动画类似

/** * 平移动画 */ public static void trans(View view) { //相对于父窗口是相对于view的父控件, 测试发现动画只在父窗口范围内显示, 超出父窗口的位置不显示 TranslateAnimation ta = new TranslateAnimation( Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.5f); // 动画播放的时间长度 ta.setDuration(2000); // 设置重复播放的次数 ta.setRepeatCount(Animation.INFINITE); // 设置重复播放的模式 ta.setRepeatMode(Animation.REVERSE); //动画结束后还原到初始状态 ta.setFillAfter(false); // 让iv播放aa动画 view.startAnimation(ta); }

4、缩放(scale)动画
/** * 缩放动画 */ public static void scale(View view) { ScaleAnimation sa = new ScaleAnimation(0.2f, 2.0f, 0.2f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); // 动画播放的时间长度 sa.setDuration(2000); // 设置重复播放的次数 sa.setRepeatCount(Animation.INFINITE); // 设置重复播放的模式 sa.setRepeatMode(Animation.REVERSE); //动画结束后还原到初始状态 sa.setFillAfter(false); // 让iv播放aa动画 view.startAnimation(sa); }

5、旋转(rotate)动画
/** * 旋转动画 */ public static void rotate(View view) { RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); // 动画播放的时间长度 ra.setDuration(2000); // 设置重复播放的次数 ra.setRepeatCount(Animation.INFINITE); // 设置重复播放的模式 ra.setRepeatMode(Animation.REVERSE); //动画结束后还原到初始状态 ra.setFillAfter(false); // 让iv播放aa动画 view.startAnimation(ra); }

6、集合(set)动画
集合动画可以将不同的动画在同一时间播放,以实现复杂的动画效果

/** * 动画合集 集合 */ public static void set(View view) { AnimationSet set = new AnimationSet(false); AlphaAnimation aa = new AlphaAnimation(0.0f, 1.0f); // 动画播放的时间长度 aa.setDuration(2000); // 设置重复播放的次数 aa.setRepeatCount(Animation.INFINITE); // 设置重复播放的模式 aa.setRepeatMode(Animation.REVERSE); RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); // 动画播放的时间长度 ra.setDuration(2000); // 设置重复播放的次数 ra.setRepeatCount(Animation.INFINITE); // 设置重复播放的模式 ra.setRepeatMode(Animation.REVERSE); ScaleAnimation sa = new ScaleAnimation(0.2f, 2.0f, 0.2f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); // 动画播放的时间长度 sa.setDuration(2000); // 设置重复播放的次数 sa.setRepeatCount(Animation.INFINITE); // 设置重复播放的模式 sa.setRepeatMode(Animation.REVERSE); TranslateAnimation ta = new TranslateAnimation( Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0.5f); // 动画播放的时间长度 ta.setDuration(2000); // 设置重复播放的次数 ta.setRepeatCount(Animation.INFINITE); // 设置重复播放的模式 ta.setRepeatMode(Animation.REVERSE); set.addAnimation(aa); set.addAnimation(ta); set.addAnimation(sa); set.addAnimation(ra); view.startAnimation(set); }

三、使用 .xml 资源文件实现动画
1、透明动画

2、平移动画

3、缩放动画

4、旋转动画

5、集合动画

6、代码实现
引用资源文件实现动画就两行代码, 工具类对其进行了简单封装

/** * 透明度渐变的动画 */ public static void alpha(Context context, View view) { anim(context, view, R.anim.anim_view_alpha); }/** * 平移动画 */ public static void trans(Context context, View view) { anim(context, view, R.anim.anim_view_trans); }/** * 缩放动画 */ public static void scale(Context context, View view) { anim(context, view, R.anim.anim_view_scale); }/** * 旋转动画 */ public static void rotate(Context context, View view) { anim(context, view, R.anim.anim_view_rotate); }/** * 连续旋转动画 */ public static void rotateContinue(Context context, View view) { anim(context, view, R.anim.anim_view_rotate_continue); }/** * 动画合集 集合 */ public static void set(Context context, View view) { anim(context, view, R.anim.anim_view_set); }/** * 资源动画 */ public static void anim(Context context, View view, int animId) { Animation aa = AnimationUtils.loadAnimation(context, animId); view.startAnimation(aa); }

四、属性动画
属性动画的四个基本动画都是使用的同一个类ObjectAnimator, 只是根据传入参数的不同来执行不同的动画, 参数有
alpha透明动画
translationXX方向平移动画

translationYY方向平移动画

scaleXX方向缩放动画

scaleYY方向缩放动画

rotationXX方向旋转动画

rotationYY方向旋转动画
具体代码封装如下:
/** * 透明度渐变的动画 * * @param view */ public static void alphaOfObject(View view) { animOfObject(view, "alpha", new float[]{ 0.2f, 0.4f, 0.6f, 0.8f, 1.0f}); }/** * 平移动画 * * @param view */ public static void transOfObject(View view) { animOfObject(view, "translationX", new float[]{10f, 20f, 30f, 40f, 60f, 80f}); }/** * 缩放动画 */ public static void scaleOfObject(View view) { // iv.setScaleX(scaleX) animOfObject(view, "scaleX", new float[]{ 1f, 2f, 3f, 4f, 5f, 6f}); }/** * 旋转动画 */ public static void rotateOfObject(View view) { animOfObject(view, "rotationY", new float[]{90f, 180f, 270f, 360f}); }/** * 属性动画(执行时不会清除原有动画) */ public static void animOfObject(View target, String propertyName, float... values) { ObjectAnimator oa = ObjectAnimator.ofFloat(target, propertyName, values); oa.setDuration(2000); oa.setRepeatCount(ObjectAnimator.INFINITE); oa.setRepeatMode(ObjectAnimator.REVERSE); oa.start(); }/** * 属性动画合集 集合 */ public static void setOfObject(View view) { AnimatorSet set = new AnimatorSet(); ObjectAnimator oa = ObjectAnimator.ofFloat(view, "translationX", new float[]{10f, 20f, 30f, 40f, 60f, 80f}); oa.setDuration(3000); ObjectAnimator oa2 = ObjectAnimator.ofFloat(view, "translationY", new float[]{-10f, -20f, -30f, -40f, -60f, -80f}); oa2.setDuration(3000); set.playTogether(oa, oa2); set.start(); }/** * 清除动画 */ public static void clearAnimation(View... views) { for (int i = 0; i < views.length; i++) { views[0].clearAnimation(); } }

五、项目地址
【Android 中动画的实现】项目地址: https://github.com/GinGod/BasisDependency , 具体参考类:BasisAnimUtils 和 AnimationActivity

    推荐阅读