Property Animation中最重要,最基础的一个类就是ValueAnimator了。Property Animation利用ValueAnimator来跟踪记录对象属性已经变化了多长时间及当前这个时间点的值。

而在ValueAnimator中,又封装了两个类:

1)TimeInterpolator,也称插值器,是来计算当前动画运动的一个跟时间有关系的比例因子。

2)TypeEvaluator,这个就是利用TimeInterpolator计算出来的因子来算出当前动画运行到的位置。

这样讲太抽象了,我们还是先用自然语言来描述一下整个动画的过程吧。

动画的原理,其实就是一帧帧的画面顺着时间顺序,在我们眼中形成视觉残留的效果。所以在动画中,时间的概念是很重要的,只有时间的变化,才能形成动画效果。

0)动画准备开始,我们在这里设置了一个动画的时长(duration),如果不设置的话,动画的时长就是300毫秒,每个画面显示的时间是10ms。同时也设置了某个属性值在这个时间段中变化的起始值start和结束值end,意思就是说,在duration时间中,属性值要从start 变化到 end。

1)动画开始了,过了 t 时间,ValueAnimator会根据 t / duration 算出一个时间消逝的比例因子(elapsed fraction),意思就是说,现在时间到 t了,我们假设总的时间的duration就是3t吧,那就是现在已经过了1/3时间了,那这个属性值也应该要变化到1/3了。

2)动画继续,现在到了2t了,那么现在动画时间已经过了2/3了,那么这个属性值是不是已经变化到2/3了呢。

3)现在到了3t了,动画结束了,属性值就已经从start变成end值了。

那么现在问题来了,如果都是这样算的话,那动画不就一直是很匀速的了吗?是的,如果用的是LinearInterpolator的话。

TimeInterpolator

TimeInterpolator就是用来改变我们这个动画速度的这样一个类了。为什么叫插值器呢?我理解就是,本来动画踩着时间点,一步一步走的挺好的,它硬生生在中间的插了些值进去,或者抽了一些值出去,让整条路变得不好走了,前面变然变上坡了,走起来就慢了,本来过去 t 时间之后,动画的画面也应该在1/3的位置了,但是路不好走,它就走不到1/3,而可能只走了1/4了,而后面是下坡,一激动,步伐就快了许多,又赶上去了,但是不管中间的路怎么变化,时间点一到,一定是刚刚好落在最终的位置上的。

Android中提供的Interpolator主要有九个:

1)AccelerateDecelerateInterpolator:先加速再减速。

2)AccelerateInterpolator:一直加速。

3)AnticipateInterpolator:先往后一下,再嗖的一声一往无前。

4)AnticipateOvershootInterpolator:先往后一下,再一直往前超过终点,再往回收一下。

5)BounceInterpolator:最后像个小球弹几下。

6)CycleInterpolator:重复几次,感觉就是环形进度条那种,具体我还没试过。

7)DecelerateInterpolator:一直减速。

8)LinearInterpolator:线性,这个就是我们上面讲到的很均匀的了。

9)OvershootInterpolator:到了终点之后,超过一点,再往回走。有个参数可以定义,超过的力度。

这些Interpolator都是实现了TimeInterpolator接口的类,它们只需要实现一个方法:getInterpolation (float input),将这个input根据自己的需求重新计算这个比例

第一步:当到了某时间t之后,ValueAnimator会算出某个比例 fraction = t / duration,而Interpolator会接收这个比例fraction,再调用其getInterpolation方法将这个比例因子重新计算一下,返回一个新的比例因子,比如LinearInterpolator实现的方法就是什么都不变,如下:

public float getInterpolation(float input) {

return input;

}而 AccelerateDecelerateInterpolator 则会利用余弦函数的对称性变化计算这个比例因子,如下:

public float getInterpolation(float input) {

return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;

}

如上所述,通过第一步 Interpolator 的插值,我们会得到一个比例因子,接下来就是要用到我们的TypeEvaluator了。

TypeEvaluator

第二步:TypeEvaluator会接受第一步中算出来的比例因子,然后算出当前的属性的值,将其返回给ValuaAnimator,由ValueAnimator去设置对应属性的值。

比如,我自己写了一个BezierTypeEvaluator,根据时间的变化来让一个按钮沿着贝塞尔曲线移动,如下:

class BezierEvaluator implements TypeEvaluator{

@Override

public PointF evaluate(float fraction, PointF startValue,

PointF endValue) {

final float t = fraction;

float oneMinusT = 1.0f - t;

PointF point = new PointF();

PointF point0 = (PointF)startValue;

PointF point1 = new PointF();

point1.set(width, 0);

PointF point2 = new PointF();

point2.set(0, height);

PointF point3 = (PointF)endValue;

point.x = oneMinusT * oneMinusT * oneMinusT * (point0.x)

+ 3 * oneMinusT * oneMinusT * t * (point1.x)

+ 3 * oneMinusT * t * t * (point2.x)

+ t * t * t * (point3.x);

point.y = oneMinusT * oneMinusT * oneMinusT * (point0.y)

+ 3 * oneMinusT * oneMinusT * t * (point1.y)

+ 3 * oneMinusT * t * t * (point2.y)

+ t * t * t * (point3.y);

return point;

}

}

自定义TypeEvaluator,我们必须实现其evaluate方法,目的就是计算出目前的对象对应属性的值,而它会接收三个参数,一个是上文中通过interpolator算出的比例,还有我们在创建动画时设置的起始值和结束值。

ValueAnimator.AnimatorUpdateListener

既然我们已经算出了在 t 时刻,对象的某个属性的值,那么我们要把这个值重新设置到对象中,才能够起作用啊。所以ValueAnimator也提供了一个内部的Listener接口,其只有一个方法,就是获取TypeEvaluator计算出来的值,并设置给对应的属性,比如我们Demo中的代码:

valueAnimator.addUpdateListener(new AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

PointF pointF = (PointF)animation.getAnimatedValue();

button.setX(pointF.x);

button.setY(pointF.y);

}

});

我们在这里改变Button的X坐标和Y坐标,从而改变其具体的位置。至于validate,然后引起重新绘制的过程,对于这些基本的属性,ValueAnimator已经帮我们实现了。

下面,我们看看效果图,然后再总结一下ValueAnimator的实现机制。

总的来说,就是三步:

1)将时间的消逝 t 和时长 duration 的比例fraction,传给interpolator 算出一个新的fractionNew。

2)将这个fractionNew传给TypeEvaluator,算出对应属性的当前值animatedValue。

3)根据animatedValue,在AnimatorUpdateListener中更新属性的值。

说到这里,那为什么我们上一篇里面都是用ObjectAnimator呢,为什么它不用AnimatorUpdateListener去更新值呢?

那是因为我们在创建ObjectAnimator的时候,已经将对应的属性名称propertyName都先告诉它了,ObjectAnimator会根据这个propertyName去找它的set方法,从而去更新值,而这也是为什么ObjectAnimator的对象一定要有对应属性的get/set方法的原因。这是它的方便之处,但同时也是它的局限之处。

如果一个系统定义的对象的某个属性没有对应的get/set方法的时候,那我们怎么办呢?

1)最简单的,就是去添加get/set方法,如果我们有权限的话,但很多时候我们没有。

2)给它添加一个包装类,引入一个get/set方法去设置本来的属性,来间接改变其值。

3)就是利用ValueAnimator,自己去实现其变动的逻辑了。

嗯,这一篇文章大概就是这样了,大家如果有兴趣了解Property Animation的应用的话,可以看一下

最后还是要提醒一下,Property Animation是3.0以后才支持的,如果大家想在3.0之前去应用这些属性的话,可以去下载jake wharton的nineoldandroids包,基本上都可以直接将方法套上,不过据我实验,还是有某些方法,比如 PropertyValuesHolder就会有些bug出现的。我把这个包也放在这里吧,

原文:http://blog.csdn.net/linmiansheng/article/details/18763987

android沿曲线移动,Android动画学习Demo(3) 沿着贝塞尔曲线移动的Property Animation相关推荐

  1. android 飘心动画(直播点赞)效果(二)---贝塞尔曲线的实现

    上篇文章 android 飘心动画(直播点赞)效果 只有代码,没有相关的说明.因为我自己也没有看懂,所以参照网上另一篇关于贝塞尔曲线实现 飘心动画的效果,目的就是 便于理解上篇文章代码的思路,然后写个 ...

  2. 一起Talk Android吧(第四百二十回:贝塞尔曲线)

    文章目录 基本概念 绘制方法 具体示例 各位看官们,大家好,上一回中咱们说的例子是"让时钟走起来",这一回咱们介绍的例子是" 贝塞尔曲线".闲话休提,言归正转, ...

  3. 贝塞尔曲线工具css,如何反转CSS中的贝塞尔曲线的实现方法

    首先来看一看我之前写的一个CSS轮播动画效果,为了让切换时动画的过渡更加的平滑我在animation-timing-function属性中并没有使用CSS提供的各种关键词,而使用了cubic-bezi ...

  4. <android>水滴效果的进度条 DripProgressView(二阶贝塞尔曲线自定义view)

    最近写了一个水滴效果的进度条,加了点特效,就是个简单的自定义view,用的二阶贝塞尔函数,如果有赶工期或者正好碰到类似效果需求的同伴们可以直接改改来用,提供 setProgress(float por ...

  5. java 贝塞尔曲线_贝塞尔曲线:原理、自定义贝塞尔曲线View、使用!!!

    一.原理 转自:http://www.2cto.com/kf/201401/275838.html Android动画学习Demo(3) 沿着贝塞尔曲线移动的Property Animation Pr ...

  6. Android 高级UI解密 (四) :花式玩转贝塞尔曲线(波浪、轨迹变换动画)

    讲解此UI系列必然少不了一个奇妙数学曲线-–贝塞尔曲线,它目前运用于App的范围是在太广了,最初的QQ气泡拖拽,到个人界面的波浪效果.Loading波浪效果,甚至于轨迹变化的动画都可以依赖贝塞尔曲线完 ...

  7. Android把商品添加到购物车的动画效果(贝塞尔曲线)

    当我们写商城类的项目的时候,一般都会有加入购物车的功能,加入购物车的时候会有一些抛物线动画,具体代码如下: 实现效果如图: 思路: 确定动画的起终点 在起终点之间使用二次贝塞尔曲线填充起终点之间的点的 ...

  8. Android开发 之 曲线运动动画(贝塞尔曲线)

    曲线运动动画(贝塞尔曲线) 贝塞尔曲线:维基百科中这样说到:在数学的数值分析领域中,贝塞尔曲线(英语:Bézier curve)是计算机图形学中相当重要的参数曲线.更高维度的广泛化贝塞尔曲线就称作贝塞 ...

  9. Android 利用二阶贝塞尔曲线自定义弧形动画

    我们先看效果 实现思路 我的思路是给自定义view(蓝色圆圈)设置值动画,值动画的估值器自定义为二阶贝塞尔曲线的估值器,至于什么二阶贝塞尔曲线,网上有很多教程,大家百度一下吧. 代码 这个项目就不贴出 ...

最新文章

  1. 聊天机器人之环境准备
  2. win7 无法复制粘贴
  3. 合并果子_tyvj1066_vijos1097_codevs1063_贪心+堆
  4. 算法基础:递归算法知识笔记
  5. CSS3 动画 思维导图
  6. St_geometry 初始用
  7. python二分法代码_Python的算法之二分法
  8. 深入C++的new(2011-11-15 15:08 )
  9. 如何查看页面是否开启gzip压缩
  10. 学习笔记——字符串方法整理
  11. MFC建立C语言项目,mfc开发(mfc项目开发实例85个)
  12. 第十四届恩智浦智能车室外电磁比赛总结
  13. Tkinter教程之Button篇
  14. [经典力学]牛顿自然哲学的数学原理论文解读
  15. dpt rp1 android apk,DPT-RP1 新固件
  16. 关于射频同轴连接器的功率容量探讨
  17. 微信小程序实现canvas画圆形微信头像
  18. 广义逆矩阵:加号逆(A+)与减号逆(A-)
  19. opengl学习笔记
  20. 卸载rasing,瑞星

热门文章

  1. 一步步实现SDDC-嵌入式PSC的VC部署
  2. Maven学习总结(43)——利用javadoc插件生成项目的API文档
  3. android 系统内测版更新,Flyme Android 10首个内测版已推送,今天你更新了吗?
  4. 制度化规范化标准化精细化_管理技巧:为什么说企业制度化管理势在必行?好处太多了...
  5. caffe图像分类教程_跟我上手深度学习: 五分钟尝试第一个深度学习(Caffe)训练和图像分类(详细图文步骤)...
  6. iframe的2个问题
  7. commons-logging和slf4j都是日志的接口
  8. nullnullProcessing Bitmaps Off the UI Thread 处理来自UI线程的位图
  9. JS分页控件,可用于无刷新分页
  10. 详解ADSL接入方式的异同比较