转载

Android属性动画使用解析-Interpolators和ViewPropertyAnimator

有关Android动画部分的内容应该已经写过四篇相关文章了,它们分别是:

  • Android补间动画Tween Animation使用解析 ;
  • Android帧动画FrameAnimation使用解析 ;
  • Android 属性动画使用解析-属性动画基本用法 ;
  • Android 属性动画使用解析-属性动画高级用法 。

其中,后两篇是介绍的属性动画相关部分,今天这篇文章所介绍的重点是动画插值器Interpolator,事实上动画插值器并不仅仅使用在属性动画上面,前面介绍补间动画的时候也使用过动画插值器Interpolator。简单说介绍一下什么是动画插值器Interpolator,动画从初始状态到结束状态进行过渡,在过渡过程中所采用的的一系列值就是插值,动画的执行时间点在时间上并不是连续的,它是在一个间断性取值的过程,人眼一秒钟可以观测到24帧,只要在一秒钟的时间内采集插值超过24次,我们所能看到的动画就是连续的。

插值器Interpolator的主要作用是控制动画变化的速率,上一篇文章介绍TypeEvaluator的时候介绍过,TypeEvaluator的核心算法是计算动画从初始值到结束值的一个线性变化取值,将TypeEvaluator的计算值与插值器Interpolator的取值进行乘法运算就决定了动画的执行状态,可以这么理解就是插值器Interpolator决定了动画加速还是减速又或者是线性的变化,插值器Interpolator取值范围一般为[0,1]。

Interpolator

Interpolator翻译成插值器,Android中它的底层实现如下:

Java

public interface TimeInterpolator {     float getInterpolation(float input); }
public interface TimeInterpolator {     float getInterpolation(float input); } 

TimeInterpolator是在Android API 11中新加入的,在之前就叫做Interpolator,在TimeInterpolator接口中只有一个方法getInterpolation需要实现,方法的返回值就是插值,插值可以大于1,也可以小于0,所以上面说Interpolator取值范围一般为[0,1],大于1或者小于0的情况也很常见,比如回弹效果。参数input的取值是[0,1]。

下面是Interpolator的代码实现:

Java

public interface Interpolator extends TimeInterpolator {      }
public interface Interpolator extends TimeInterpolator {      } 

Interpolator仅仅继承了TimeInterpolator没有做任何事情。

动画如果不设置插值器Interpolator,默认采用的是一个先加速后减速的插值器AccelerateDecelerateInterpolator。

系统已经内置了许多插值器,API 22中的如下:

  • AccelerateDecelerateInterpolator 在动画开始与介绍的地方速率改变比较慢,在中间的时候加速
  • AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
  • AnticipateInterpolator 开始的时候向后然后向前甩
  • AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
  • BounceInterpolator 动画结束的时候弹起
  • CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
  • DecelerateInterpolator 在动画开始的地方快然后慢
  • LinearInterpolator 以常量速率改变
  • OvershootInterpolator 向前甩一定值后再回到原来位置
  • PathInterpolator 路径插值器

简单插值器分析

插值器Interpolator位于android.view.animation包下,为了验证插值器的二次曲线效果,有两个网址可以帮助我们实时查看 inloop.github.io/interpolator/ 和 www.wolframalpha.com/ 。

LinearInterpolator

函数:y=t;

Android属性动画使用解析-Interpolators和ViewPropertyAnimator

下图是动画及插值取点的动态图:

Android属性动画使用解析-Interpolators和ViewPropertyAnimator

ViewPropertyAnimator

我们在开发过程中对动画的处理最常见的还是对View的处理,属性动画操作相对来说比补间动画已经简单了许多,那么面对最常见的View的动画处理是不是仍然有更简单的处理方式呢?这个答案是肯定的,就在 ViewPropertyAnimator类中,接下来通过一个例子进行对比介绍。

ViewPropertyAnimator是在Android3.1版本推出的,它不是什么高级类,只是为了更简单方面的操作View,因为多数动画都是针对View,Google开发团队也意识到了这一点,于是一个简约而不简单的动画操作类ViewPropertyAnimator就诞生了。

如果我们想将一个图片在x方向平移100像素,在y方向平移200像素,在上一篇文章中我们将结果组合动画可以将单个动画进行组合播放,可以设计两个动画,一个动画进行x方向平移,另一个动画进行y方向平移,这也是最容易想到的一种解决方式了。

AnimatorSet实现方式

Java

ObjectAnimator animX = ObjectAnimator.ofFloat(imageView, "x", 100f); ObjectAnimator animY = ObjectAnimator.ofFloat(imageView, "y", 200f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
ObjectAnimatoranimX = ObjectAnimator.ofFloat(imageView, "x", 100f); ObjectAnimatoranimY = ObjectAnimator.ofFloat(imageView, "y", 200f); AnimatorSetanimSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start(); 

组合动画AnimatorSet确实可以实现效果,可是我们也发现了,如果我们一个特效用到平移旋转再加上透明度的变化,仅仅一个动画我们就要定义好几个ObjectAnimator对象,逻辑上虽然清晰但是结构确实有些冗余了。

PropertyValuesHolder

在Android中如果要实现单个对象不同属性的动画效果,可以使用组合动画AnimatorSet之外,我们还可以使用PropertyValuesHolder来实现,具体做法如下:

Java

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 100f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 200f); ObjectAnimator.ofPropertyValuesHolder(imageView, pvhX, pvhY).start();
PropertyValuesHolderpvhX = PropertyValuesHolder.ofFloat("x", 100f); PropertyValuesHolderpvhY = PropertyValuesHolder.ofFloat("y", 200f); ObjectAnimator.ofPropertyValuesHolder(imageView, pvhX, pvhY).start(); 

PropertyValuesHolder用于保存单个属性的动画效果,在使用上大致分为以下三个步骤:

  1. 我们可以通过 PropertyValuesHolder类的工厂方法ofInt, ofFloat等方法,让它能够Hold住对应property的value。
  2. 在利用ObjectAnimator的ofPropertyValuesHolder方法时,再将我们上面定义的PropertyValuesHolder给传进去,定义出一个ObjectAnimator。
  3. 设置ObjectAnimator对应的属性,调用其start方法就行。

上面虽然只使用了一个ObjectAnimator,但是跟组合动画比较起来也是伯仲之间,代码结构也不简单,下面才是最简单的实现方式。

ViewPropertyAnimator

ViewPropertyAnimator将图片平移一行代码就搞定了,代码如下:

Java

imageView.animate().x(100f).y(200f);
imageView.animate().x(100f).y(200f); 

上面代码中感觉并没有使用到ViewPropertyAnimator类,事实上该类是借助View的animate方法返回的,然后我们就可以直接调用动画方法了,每一个动画方法都是返回的ViewPropertyAnimator实例,该种实现方式跟Builder建造者模式差不多,每次调用之后都返回自己。

在使用ViewPropertyAnimator时,我们自始至终没有调用过start()方法,这是因为新的接口中使用了隐式启动动画的功能,只要我们将动画定义完成之后,动画就会自动启动。并且这个机制对于组合动画也同样有效,只要我们不断地连缀新的方法,那么动画就不会立刻执行,等到所有在ViewPropertyAnimator上设置的方法都执行完毕后,动画就会自动启动。当然如果不想使用这一默认机制的话,我们也可以显式地调用start()方法来启动动画。

结束语

Android动画方面的相关笔记到今天为止已经5篇了,接下来还想再补上一篇,是一篇针对更高API动画特效的介绍,就是在MetrialDesign中常用的部分特效。动画部分知识点暂时记录到这个深度,随着开发水平不断增进将来还会继续查漏补缺,针对动画部分的理解应用目前还是停留在表面,如果想要在实际项目中融会贯通详细还需要一些时间的沉淀,好吧,就这么多……

原文  http://www.sunnyang.com/406.html
正文到此结束
Loading...