教你做出炫酷的Android动画效果
前言
Android动画也是Android系统中一个很重要的板块, 在平常开发中, 为了做出炫酷的效果, 动画可以说是必不可少的; 本文将总结Android中与动画相关的部分, 文中部分内容整理自文末参考链接, 权作笔记~
需要公告的是文章不会详细通过源码去讲解各种动画的实现细节, 由于相对来说, 动画的熟练使用更为重要, 所以本文只是提一下关键的动画源码部分
正文
一. 概述
Android中动画分为三大类: View动画, Transition(过渡动画), 属性动画; 下文也将从这三个方面进行总结和讲解
动画的本质实际上就是将作用对象的属性值在一段时间内缓慢的改变, 将每一个小的时间片段对应的属性值改变作用到对象并进行不断重绘, 造成肉眼看起来的的动画效果~
二. View动画
2.1 基本使用总结
View动画分为四种, 如下表:
| 名称 | 标签 | 子类 | 效果 |
|---|---|---|---|
| 平移动画 | <translate> | TranslateAnimation | 移动 |
| 缩放动画 | <scale> | ScaleAnimation | 缩放 |
| 旋转动画 | <rotate> | RotateAnimation | 旋转 |
| 透明度 | <alpha> | AlphaAnimation | 透明度 |
注: 动画中还有一种叫帧动画, 这里也归为View动画中, 后文单独讲解
View动画可以使用xml形容, 也可以使用代码形容(即便用上表中的四个子类); 使用xml形容的语法格式如下:
注: 位置为res/anim/filename.xml
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@[package:]anim/interpolator_resource" android:shareInterpolator="[true | false]" android:fillAfter="[true | false]" android:duration="int" android:repeatMode="[reverse | restart]"> <alpha android:fromAlpha="float" android:toAlpha="float" /> <scale android:fromXScale="float" android:toXScale="float" android:fromYScale="float" android:toYScale="float" android:pivotX="float" android:pivotY="float"/> <translate android:fromXDelta="float" android:toXDelta="float" android:fromYDelta="float" android:toYDelta="float"/> <rotate android:fromDegrees="float" android:toDegrees="float" android:pivotX="float" android:pivotY="float"/> <set> ... </set></set>解释:
<set>代表AnimationSet, 可以包含若干动画android:shareInterpolator: 表示集合中的动画能否和集合共享同一个插值器; 假如集合不指定插值器, 那么子动画需要单独指定或者者使用默认插值器android:pivotX: 轴点x坐标android:pivotY: 轴点y坐标android:fillAfter: 动画结束之后,View能否停留在结束位置,true表示停留在结束位置,false表示不停留
在代码中使用View动画:
Button button = findViewById(R.id.button);Animatoin animation = AnimationUtils.loadAnimation(this, R.anim.animation_item);button.startAnimation(animation);2.2 自己设置View动画
TranslateAnimation, ScaleAnimation, RotateAnimation, 和AlphaAnimation都继承自Animation; 假如要自己设置View动画的话, 也需要继承Animation, 并重写Animation.initialize()和Animation.applyTransformation()方法; initialize()顾名思义就是进行少量初始化工作, 比方设置属性的初始值等, applyTransformation()就是根据时间的流失量来计算出当前时间片段所对应的属性值, 并设置到对应的作用对象(对于View动画来说该对象就是View); 这里的设置往往是通过Matrix来作用的, 如下以TranslateAnimation.applyTransformation()为例
@Overrideprotected void applyTransformation(float interpolatedTime, Transformation t) { float dx = mFromXDelta; float dy = mFromYDelta; if (mFromXDelta != mToXDelta) { dx = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime); // 通过时间流失量计算出x的改变量 } if (mFromYDelta != mToYDelta) { dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime); // 通过时间流失量计算出y的改变量 } t.getMatrix().setTranslate(dx, dy); // 通过Matrix作用到对象}上述代码其实也可以当做自己设置View动画的模板代码, 自己设置View动画时, 可以使用Camera来配合计算改变量; 关于Camera和Matrix的使用, 可以参见博客
2.3 帧动画
帧动画就是顺序播放一组预先定义好的图片, 系统提供了AnimationDrawable来使用帧动画
xml定义如下:
注: 位置为/res/drawable/filename.xml
<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/item" android:duration="100"/> <item android:drawable="@drawable/item" android:duration="100"/> <item android:drawable="@drawable/item" android:duration="100"/> <item android:drawable="@drawable/item" android:duration="100"/></animation-list>使用帧动画时, 当图片较多或者者较大时可能引起OOM
三. Transition(过渡动画)
过渡动画其实是用于控制ViewGroup的Item的出场效果, 或者者Activity之间的切换效果等
3.1 LayoutAnimation
xml实现格式如下:
注: 位置为/res/anim/anim_layout.xml
<?xml version="1.0" encoding="utf-8"?><layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:delay="0.5" android:animationOrder="[normal | reverse | random]" android:animation="@anim/anim_item"/>解释:
android:delay: 子元素推迟多少时间执行动画; 比方子元素入场动画时间周期为300ms, 那么0.5表示每个每个子元素都需要推迟150ms才能播放入场动画, 总体来说, 第一个子元素推迟150ms开始播放动画, 第二个子元素推迟300ms开始播放动画, 以此类推android:animationOrder:normal表示顺序显示, 即排在前面的子元素先开始动画;reverse表示逆向显示;random表示随机显示
当定义好layoutAnimation之后, 在布局文件中即可以通过ViewGroup的属性android:layoutAnimation="@anim/anim_layout"来指定入场动画了~
代码实现, 格式如下: 即通过LayoutAnimationController实现
ListView listView = findViewById(R.id.list);Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item);LayoutAnimationController controller = new LayoutAnimationController(animation);controller.setDelay(0.5f);controller.setOrder(LayoutAnimationController.ORDER_NORMAL);listView.setLayoutAnimation(controller);3.2 Activity的切换效果
- 当启动一个
Activity的时候, 可以按照如下方式为其增加自己设置的切换效果:
Intent intent = new Intent(this, AnimActivity.class);startActivity(intent);overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim);- 当
Activity退出时, 可以如下增加切换效果:
@Override public void finish() { super.finish(); overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); }可以看出, 都是使用overridePendingTransition()来指定切换动画, 同时需要注意的是这个方法必需在startActivity(intent)或者者finish()之后被调用才能生效
- 为
Fragment增加切换动画: 可以通过FragmentTransaction.setCustomAnimations()来增加切换动画; 需要注意的是该动画必需是View动画, 不能用属性动画(由于属性动画在API 11引入,Fragment也是API 11才引入的)
四. 属性动画
属性动画是在Android 3.0(API 11)开始引入的; 属性动画可以用xml实现, 也可以用代码实现, 但是一般都是用代码实现
4.1 基本使用
4.1.1 ViewPropertyAnimator
操作View属性值, 可以通过View.animate()来获取一个ViewPropertyAnimator对象, 而后即可以通过ViewPropertyAnimator来操作该对象的属性值了~ 可以操作的属性值参见下图

使用示例如View.animate().setDuration(500).alpha(0.5);
4.1.2 ObjectAnimator
也是针对View的特定属性, 同时还要求该属性提供了对应的set和get方法, 基本使用如下; 由于ObjectAnimator是通过属性的set方法来不断改变属性值的, 所以set方法是肯定需要的, 至于get方法只是用于获取动画开始的初始值的, 假如明确指定了初始值的话, 也可以提供get方法(假如没有提供get方法, 同时又没有指定初始值的话, 将Crash; 假如没有set方法, 不会Crash, 只是没有效果而已)
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0, 65);animator.start();假如一个属性没有set方法的话, 处理方法有以下三种:
假如有权限的话, 自己给对象加上
set和get方法用一个类来包装原始对象, 间接为其提供
set和get方法采用
ValueAnimator, 监听动画过程, 自己实现属性改变
4.2 插值器
所谓插值器就是属性改变的速度, 系统提供了如下插值器:
| AccelerateDecelerateInterpolator | LinearInterpolator | AccelerateInterpolator |
| DecelerateInterpolator | AnticipateInterpolator | OvershootInterpolator |
| AnticipateOvershootInterpolator | BounceInterpolator | CycleInterpolator |
| PathInterpolator | | |
| FastOutLinearInInterpolator | FastOutSlowInInterpolator | LinearOutSlowInInterpolator |
其中FastOutLinearInInterpolator, FastOutSlowInInterpolator, LinearOutSlowInInterpolator是Android 5.0(API 21)引入的三个新的 Interpolator模型, 并把它们加入了support v4包中
4.3 估值器
估值器即TypeEvaluator, 作用是根据当前属性改变的百分比来计算改变后的属性值, 用于协助插值器实现非线性运动; 系统提供了如下估值器:
| IntEvaluator | IntArrayEvaluator | FloatEvaluator |
| FloatArrayEvaluator | ArgbEvaluator | PointFEvaluator |
| RectEvaluator | | |
假如要对其余类型做动画(非int, float, Color), 那么需要自己设置类型估值算法, 即继承TypeEvaluator自己实现其evaluate()方法就可
估值器基本使用如下:
ObjectAnimator anim = ObjectAnimator.ofObject(view, "alpha", new FloatEvaluator(), 0, 1);4.4 监听器
ViewPropertyAnimator和ObjectAnimator设置监听器的方法如下表:
| ViewPropertyAnimator | setListener() | setUpdateListener() | withStartAction() | withEndAction() |
| ObjectAnimator | addListener() | addUpdateListener() | addPauseListener() | |
注:
ViewPropertyAnimator可以通过setListener()和setUpdateListener()来设置监听器, 移除监听器可以通过setListener(null)和setUpdateListener(null)来移除;ViewPropertyAnimator独有的withStartAction()和withEndAction()方法, 可以设置一次性(动画结束后就自动弃掉了, 即一次有效)的动画开始或者结束的监听ObjectAnimator则是用addListener()和addUpdateListener()来增加一个或者多个监听器, 移除监听器则是通过removeListener()和removeUpdateListener()来指定移除对象;ObjectAnimator支持使用pause()方法暂停, 所以它还多了一个addPauseListener()和removePauseListener()的支持ViewPropertyAnimator.withStartAction/EndAction()是ViewPropertyAnimator的独有方法, 它们和set/addListener()中回调的onAnimationStart()和onAnimationEnd()相比起来的不同主要有两点:
withStartAction()和withEndAction()是一次性的, 在动画执行结束后就自动弃掉了, 就算之后再重用ViewPropertyAnimator来做别的动画, 用它们设置的回调也不会再被调用; 而set/addListener()所设置的AnimatorListener是持续有效的, 当动画重复执行时, 回调总会被调用withEndAction()设置的回调只有在动画正常结束时才会被调用, 而在动画被取消时不会被执行; 这点和AnimatorListener.onAnimationEnd()的行为是不一致的
监听器方法有:
| AnimatorListener | onAnimationStart() | onAnimationEnd() | onAnimationCancel() | onAnimationRepeat() |
注: 即便动画通过cancle()方法取消, onAnimationEnd()也会被调用; 所以当动画被取消时, 假如设置了AnimatorListener, 那么 onAnimationCancel()和onAnimationEnd()都会被调用; onAnimationCancel()会先于onAnimationEnd()被调用; 因为ViewPropertyAnimator不支持重复, 所以这个方法对ViewPropertyAnimator相当于无效
五. 动画注意事项
避免使用帧动画, 易造成
OOM动画需要考虑暂停和取消; 属性动画中有一类无线循环的动画, 这类动画在
Activity退出时要及时中止, 否则将导致Activity无法释放从而造成内存泄露; 通过验证后发现View动画无此问题使用
View动画之后可能会出现View无法隐藏的现象, 即setVisibility(View.GONE)失效了, 此时可以使用view.clearAnimation()来清理View动画就可Android 3.0以前系统, 不论是View动画还是属性动画, 都只是作用于View内容(由于Android 3.0以前, 属性动画底层其实也是通过View动画实现的), 新位置无法触发单击事件; 从3.0开始, 属性动画的单击事件触发位置为移动后的位置, 但是View动画依然在原位置
现在加Android高级开发群;701740775,可免费领取一份最新Android高级架构技术体系大纲和进阶视频资料,以及这些年年积累整理的所有面试资源笔记。加群请备注简书领取xx资料
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 教你做出炫酷的Android动画效果