自从Android3.0 版本加入属性动画后,在平时的开发中多多少少也使用了,但是从来没有对其做一个系统的分析和总结,最近刚好有点时间,来对这个话题做一个分析和总结。

  • 概述

    • Android动画体系
    • 引入属性动画的原因
    • 属性动画工作原理
    • 如何使用属性动画
      • ObjectAnimator使用方式
      • ValueAnimator使用方式
    • 深入理解
    • 注意事项
  • 总结

概述

动画对于GUI程序总是一个绕不过的话题,适当的动画可以使我们的人机交互界面更加的生动有趣,所以Android也提供了一套自己的动画体系。

Android动画体系

至Android3.0以后(其实都不用再提这一点了,因为到目前为止,Android版本基本上已经收缩到4.0以上了),Android动画体系分为:

  1. 视图动画(View Animation)

    • 补间动画(Tween Animation)
    • 逐帧动画(Frame Animation)
  2. 属性动画(Property Animation)

引入属性动画的原因

其实这就是废话,肯定是View 动画存在一些问题,才引入新的解决方案。重点是View 动画存在哪些问题,而属性动画如何解决的这些问题,这个才是我们需要关注的重点,因为只有了解了一项技术的使用场景才能在日常的开发当中游刃有余的使用这些技术。

View 动画存在以下这些问题:

  1. 只能对View对象做动画
    例如我们要对一个视图的背景颜色做动画,使用View 动画就无法完成
  2. 动画效果有限
    补间动画只有移动旋转缩放变换透明度四种动画效果。
  3. 只改变了View的视觉效果,却没有真正改变View本身
    例如我们通过View平移动画将一个buttonA位置移动到了B位置,当我们点击B位置上的按钮时候什么都不会发生,而点击A位置却触发了button的点击事件。

属性动画就是为了解决以上问题而被引入的,但是View动画仍然有自己存在的价值,它仍然有适合自己的使用场景,而其运行效率以及使用复杂度都低于属性动画,所以还是应了那句老话,合适的就是最好的。我们开发中应该最求使用合适的技术来解决相应的问题。

属性动画工作原理

首先我们应该明白我们所说的动画是如何产生的。动画的本质可以理解为一系列连续图片(帧)快速不断的通过一个窗口展示在你的眼前。而人眼是有“视觉暂留”的,即人眼在某个视像消失后,仍可使该物像在视网膜上滞留0.1-0.4秒左右。这样当上一张图片的残像没有消失之前,下一张图片就有进入了你的眼睛,而这两张图片的变化的轻微的,所以你感觉动画丝滑细腻,无卡顿。

Android中的属性动画也逃不出这个套路。在一定时间间隔内(动画时长),通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果。

举个例子,Button 具有一个控制背景颜色的属性“backgroundColor”,那么属性动画就是通过不断的改变该属性的值,改变一次就相当于生成一幅图片展示在用户眼前,这样通过在一定的时间内以一定的频率不断重复这个动作,直到属性值达到了预先设置的值,动画结束。

上一幅Carson_Ho博客(https://blog.csdn.net/carson_ho/article/details/72909894)的一张流程图,画的很清楚,就是有点糊。

如何使用属性动画

一项技术首先要会使用,然后才是深入理解其内部细节,进而用的更好!

属性动画主要有三个类,AnimatorValueAnimatorObjectAnimator,这三个类从右往左依次继承关系,那有点编程经验的同学应该知道哪个使用起来最简单了吧,没错就是ObjectAnimator,因为他最具体,最针对某一特定情形,那样它就被封装的最完善,当然代价就是会损失一定的灵活性。那我们先从简单的开始看。

ObjectAnimator使用方式

ObjectAnimator 有好多公共静态方法可以构造动画对象,如下图所示

我们只介绍第一个,也是最简单最常用的一个,其他的思想类似,请自行研究。属性动画既可以像view动画那样以xml的形式构建,也可以使用java代码构建。然而在实际开发中我们更多的是使用java代码构建的方式,所以此处只介绍使用java代码实现属性动画的方法。

public static ObjectAnimator ofFloat(Object target, String propertyName, float… values)
参数1:操作的对象,例如我接下来要操作一个Textview
参数2:操作的属性名称
参数3:操作属性的变化路径值,例如只传入一个参数a,则表示此属性值从当前值变化到目 标值a;如果传入两个参数a,b,则表示此属性值从a变化到b;如果传入3个参数值a,b,c,则此属性值从a变化到b再变化到c,以此类推。
当构建出ObjectAnimator 后就可以对其做一下自定义的配置了,例如,动画执行时长,动画延迟开始的时间,动画重复的策略,重复的次数等。

正所谓:Talk is cheap, show me the code,来咱们看代码

ObjectAnimator tAni= ObjectAnimator.ofFloat(tvOpr,"translationY",600);
tAni.setDuration(2000);//设置动画时长2秒,如果不设置会采用系统默认值300
tAni.start();

上面的代码在2秒的时间内将tvOpr-一个TextView从它当前的位置沿着Y轴移动到了600px的位置。如下图所示

ObjectAnimator rAni= ObjectAnimator.ofFloat(tvOpr,"rotationY",0,360);
rAni.setDuration(2000);
rAni.start();

上面的代码在2秒的时间内将tvOpr-一个TextView绕Y轴从0旋转到360度。如下图所示

我们还可以使用AnimatorSet类将不同的动画组合起来

 AnimatorSet aSet=new AnimatorSet();ObjectAnimator tAni2= ObjectAnimator.ofFloat(tvOpr,"translationY",600);tAni2.setDuration(2000);ObjectAnimator rAni2= ObjectAnimator.ofFloat(tvOpr,"rotationY",0,360);rAni2.setDuration(2000);aSet.playTogether(tAni2,rAni2);aSet.setDuration(2000).start();

上面的代码在2秒内完成了旋转和纵向平移的动画,如下图所示

通过以上的示例代码相信大家已经知道如何使用ObjectAnimator 了,值得注意的是,我们要改变的那个属性必须有Set()Get()方法,Get()方法在传入初始值的情况下可以省略,但是最好两个都有。如果要操作一个没这两个方法的对象怎么办呢,待深入分析的部分讲解。

ValueAnimator使用方式

ValueAnimator 本身并不作用于任何对象,其是对一个值进行动画,而我们可以监听到这个过程,然后在此过程中修改我们想要做动画的属性值。

ValueAnimator 有几个公共静态方法可以构造动画对象,如下图所示

我们以ofInt 来做一个说明
public static ValueAnimator ofInt(int… values)

   private void changeAlpha(){// 步骤1:设置动画属性的变化路径ValueAnimator anim = ValueAnimator.ofInt(255,0, 255);// ofInt()作用有两个// 1. 创建动画实例// 2. 将传入的多个Int参数进行平滑过渡// 如果传入了3个Int参数 a,b,c ,则是先从a平滑过渡到b,再从b平滑过渡到C,以此类推// ValueAnimator.ofInt()内置了整型估值器,直接采用默认的.不需要设置,即默认设置了如何从初始值过渡到结束值// 步骤2:设置动画的播放各种属性anim.setDuration(4000);// 设置动画运行的时长anim.setStartDelay(0);// 设置动画延迟播放时间anim.setRepeatCount(0);// 设置动画重复播放次数 = 重放次数+1  动画播放次数 = infinite时,动画无限重复anim.setRepeatMode(ValueAnimator.REVERSE);//RESTART(默认):正序重放 REVERSE:倒序回放anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){@Overridepublic void onAnimationUpdate(ValueAnimator animation){int currentValue = (Integer) animation.getAnimatedValue();//步骤3: 获得改变后的值0到255float fraction=animation.getAnimatedFraction();//当前动画进度System.out.println(currentValue);// 输出改变后的值// 步骤4:将改变后的值赋给对象的属性值tvOpr.getBackground().setAlpha(currentValue);// 步骤5:刷新视图,即重新绘制,从而实现动画效果tvOpr.requestLayout();}});anim.start();}

上面的代码在4秒的时间内将tvOpr-一个TextView背景透明度从完全不透明变到完全透明又变到完全不透明,如下图所示

深入理解

由于属性动画的工作原理比较简单,就是通过不断的调用要做动画的属性的Set()方法来改变此属性的值,进而造成了动画的效果。值得深入探讨的地方集中在如下两方面:

  • 动画是以何种方式进行的?例如是匀速的,还是加速的,还是按照贝塞尔曲线运动的,等等
  • 动画进行到某一刻,那个属性的值是如何计算出来的?

第一问题由属性动画中的插值器(Interpolator)来解决,第二个问题由估值器(TypeEvaluator)来解决 这两个很重要,正是由于他们的存在我们才可以实现非匀速的动画效果。TypeEvaluator 依赖Interpolator 工作,在TypeEvaluator的估值函数中,是需要Interpolator 的计算结果的。Android已经为我们内置几个插值器与估值器

插值器LinearInterpolatorAccelerateDecelerateInterpolatorDecelerateInterpolatorAccelerateInterpolator

估值器IntEvaluatorFloatEvaluatorArgbEvaluator

下面我们通过一个自定义二次贝塞尔曲线的View来说明插值器估值器的使用方式,此View 出自chenwei.li的同学之手,我只是更正了其中的一些错误。冒着博客篇幅太长的风险,还是决定将完整代码贴出来。

public class BezierMoveView extends View implements View.OnClickListener {//开始点和结束点private int mStartXPoint;private int mStartYPoint;private int mEndXPoint;private int mEndYPoint;//控制点private int mConXPoint;private int mConYPoint;//移动点private int mMoveXPoint;private int mMoveYPoint;//路径和画笔private Path mPath;private Paint mPaint;//圆形半径,画笔private int mCircleRadius;private Paint mCirlcePaint;public BezierMoveView(Context context) {super(context);init(context);}public BezierMoveView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public BezierMoveView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}/*** 进行初始化的一些操作*/private void init(Context context) {//设置各点的位置mStartXPoint = 100;mStartYPoint = 100;mEndXPoint = 600;mEndYPoint = 600;mConXPoint = 400;mConYPoint = 0;mMoveXPoint = 100;mMoveYPoint = 100;//路径,画笔设置mPath = new Path();mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setColor(Color.BLUE);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(5);mCircleRadius = 20;mCirlcePaint = new Paint(Paint.ANTI_ALIAS_FLAG);mCirlcePaint.setColor(Color.BLUE);mCirlcePaint.setStyle(Paint.Style.FILL);setOnClickListener(this);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mPath.reset();//贝塞尔曲线mPath.moveTo(mStartXPoint, mStartYPoint);mPath.quadTo(mConXPoint, mConYPoint, mEndXPoint, mEndYPoint);canvas.drawPath(mPath, mPaint);//画圆canvas.drawCircle(mStartXPoint, mStartYPoint, mCircleRadius, mCirlcePaint);canvas.drawCircle(mMoveXPoint, mMoveYPoint, mCircleRadius, mCirlcePaint);canvas.drawCircle(mEndXPoint, mEndYPoint, mCircleRadius, mCirlcePaint);}@Overridepublic void onClick(View v) {ValueAnimator valueAnimator = ValueAnimator.ofObject(new CirclePointEvaluator(), new Point(mStartXPoint, mStartYPoint),new Point(mEndXPoint, mEndYPoint));valueAnimator.setDuration(2000);valueAnimator.setInterpolator(new  AccelerateDecelerateInterpolator());valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {Point point = (Point) animation.getAnimatedValue();mMoveXPoint = point.x;mMoveYPoint = point.y;invalidate();}});valueAnimator.start();}public class CirclePointEvaluator implements TypeEvaluator {@Overridepublic Object evaluate(float t, Object startValue, Object endValue) {Point startPoint = (Point) startValue;Point endPoint = (Point) endValue;float temp = 1 - t;int x = (int) (temp * temp * startPoint.x + 2 * t * temp * mConXPoint + t * t * endPoint.x);int y = (int) (temp * temp * startPoint.y + 2 * t * temp * mConYPoint + t * t * endPoint.y);return new Point(x,y);}}
}

重点看代码靠下位置的onClick 和下面的自定义估值器代码。当我们点击这个view的时候,会触发一个动画,这个动画使用如下方法设置插值器,此处为加速减速插值器
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());,而且设置了自定义的CirclePointEvaluator 估值器,动画每执行一帧,监听就会被回调,然后在回调方法onAnimationUpdate()中获得了当前的属性值,更改小球的位置坐标,然后触发重绘。

所以使用ValueAnimator 可以做出非常绚烂的效果。

注意事项

如果动画设置为无限循环,在退出Activity时注意销毁,防止内存泄漏。

总结

又一次验证了我们老祖宗那句老话:万事开头难。曾几何时,我对Android的属性动画是怀着一个恐惧和抵触的心里,不愿意静下心来研究总结。希望自己做事再专注一点,踏实一点。

源代码下载地址

秒懂Android属性动画相关推荐

  1. android动画封装,Android属性动画封装,快速构建动画

    Android实现动画效果的方式主要有帧动画.补间动画.属性动画.关于安桌动画的基础知识可以查看这篇文章Android属性动画完全解析 这里我要讲的是如何快速构建出一个动画效果,如下图: 如果我们用属 ...

  2. Android属性动画 ObjectAnimator

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/118709616 本文出自[赵彦军的博客] 文章目录 ObjectAnimator ...

  3. (转)Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法

    版权声明:本文出自郭霖的博客,转载必须注明出处. 目录(?)[-] ValueAnimator的高级用法 ObjectAnimator的高级用法 转载请注明出处:http://blog.csdn.ne ...

  4. android 属性动画实例,Android属性动画完全解析 中 ,ValueAnimator和ObjectAnimator的高级用法...

    大家好,在上一篇文章当中,我们学习了Android属性动画的基本用法,当然也是最常用的一些用法,这些用法足以覆盖我们平时大多情况下的动画需求了.但是,正如上篇文章当中所说到的,属性动画对补间动画进行了 ...

  5. Android 系统(196)---Android 属性动画

    Android 属性动画 属性动画 总结&攻略 前言 动画的使用 是 Android 开发中常用的知识 本文将详细介绍 Android 动画中 属性动画的原理 & 使用 动画类型 关于 ...

  6. Android 属性动画Property Animation(中)

    Android 属性动画Property Animation(上)介绍了属性动画的概念以及相关的类和接口,本篇来看下具体肿么使用. ValueAnimator ValueAnimator指定整形.浮点 ...

  7. Android 属性动画使用(二)

    首先扯点别的:晚上稍微跑了一会步,然后逛了超市,晚饭喝的南瓜粥,吃了一碗面条,今天不是太饿,现在正一边吃着葡萄一边学习,也是没谁了. 比如说,我们想要实现从0过渡到100,使用ValueAnimato ...

  8. android+属性动画+高度,android 自定义view+属性动画实现充电进度条

    近期项目中需要使用到一种类似手机电池充电进度的动画效果,以前没学属性动画的时候,是用图片+定时器的方式来完成的,最近一直在学习动画这一块,再加上复习一下自定义view的相关知识点,所以打算用属性动画和 ...

  9. Android 属性动画(一)新手入门

    一.属性动画简介 Android 中动画有很多种,属性动画就是其中的一种.所谓的属性动画,就是在指定的时间内,通过改变对象的属性达到变化效果的动画.在 Android 中,属性动画系统是一个强健的框架 ...

最新文章

  1. docker镜像的备份和恢复
  2. 理解 UDDI(统一描述、发现和集成)
  3. 2013年4月20日 通用权限管理系统组件V3.8功能改进说明
  4. 完全二叉树基本操作(不含遍历)
  5. Reading SBAR SDN flow-Based monitoring and Application Recognition
  6. abstract类中不可以有private的成员_C++中public、protected、private的区别
  7. JAVA中“:”的用法详解
  8. 数据中心效率:40%的改进是通过最佳实践方案
  9. 微软新版搜索的雄心与春梦
  10. LPC1788 NVIC 的设置
  11. word转换高清PDF
  12. OJ每日一练——计算分数加减表达式的值
  13. HDU5442 最小(大)表示法
  14. linux awk 字符串匹配,awk匹配字符串
  15. 手机浏览器java_三款最热java手机浏览器横评(组图)
  16. 安全检查监理项目部材料清单
  17. 企业中如何做好文化建设?
  18. 英语发音规则---B字母
  19. JAVA实现打字小游戏
  20. Filezilla+花生壳内网穿透实现外网可以访问 避坑指南

热门文章

  1. [笛卡儿积]业务中的复选框条件--输出所有的情况结果
  2. 利用tushare pro根据财务指标选股
  3. 《零基础D编程入门》
  4. 图的连通性和连通分量
  5. 彩灯控制单片c语言程序,基于51单片机的led彩灯设计。 9个灯(红绿蓝三色)。按键控制 c语言程序...
  6. DBD::mysql的安装
  7. 【汇编 C】循环语句goto、while、dowhile、for
  8. Mac:TexStudio 中文论文模版
  9. Qt模仿Boss直聘的竞争力分析器
  10. kubeadm故障排除