一、概述
Android在API11后加入的新特性,主要通过对对象的属性动态改变实现动画效果,也因此大大扩展了作用对象,并且由于直接对属性进行变换,动画效果也更丰富。主要有ValueAnimator、ObjectAninmator、AnimatorSet等概念。
二、属性动画的分类及使用
1、ObjectAnimator 继承自ValueAnimator,使用举例如下
ObjectAnimator.ofFloat(button,"translationY",100).setDuration(2000).start();
传入作用对象,属性名称、变化值,并可设置相关参数,最后调用start开始动画。
2、ValueAnimator 可以改变任意一个属性,但没有作用对象,只产生属性值的变化,使用时可以为其添加监听。属性动画的监听接口主要有两个,AnimateUpdateListener和AnimateListener。其中前者为逐帧监听,后者则是监听不同的四个状态,与View动画的监听类似。
在使用该对象时,可以在AnimateUpdateListener的监听方法中逐帧获得Animator的属性值,由此动态的设置动画的作用对象实现动画效果。代码如下:
ValueAnimator colorAnim = ObjectAnimator.ofInt(this,"backgroundColor",0xFFFF8080,0xFF8080FF); colorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int colorValue = (int) animation.getAnimatedValue(); button.setBackgroundColor(colorValue); } }); colorAnim.setDuration(3000); colorAnim.setEvaluator(new ArgbEvaluator()); colorAnim.setRepeatCount(ValueAnimator.INFINITE); colorAnim.setRepeatMode(ValueAnimator.REVERSE); colorAnim.start();
由此可对任意属性进行动画,除此之外还有两种不同的方法实现任意属性动画。
其中getAnimatedValue是获得当前进度值,与创建对象时传入的始末值有关,除此之外还可以利用Evaluator(估算器)计算得到所需的属性值,代码如下
float fraction = animation.getAnimatedFraction(); target.getLayoutParams().width = intEvaluator.evaluate(fraction,start,end); target.requestLayout();
通过获得getAnimatedFraction获得fraction,再利用IntEvaluator对象传入fraction、start(属性初值),end(属性末值)计算得到当前属性值,由此也可以使用自定义的Evaluator来计算属性值得到更灵活的动画效果。
requestLayout是当View确定自身已不适合现有区域时,调用该方法重新完成measure和layout过程以刷新位置。
3、AnimatorSet 动画集合,顾名思义,可设置多个动画效果,使用很简单,如下
AnimatorSet set = new AnimatorSet(); set.playTogether(ObjectAnimator.ofFloat(/*设置动画效果及对象*/), ObjectAnimator.ofFloat(/*设置动画效果及对象*/), ObjectAnimator.ofInt(/*设置动画效果及对象*/)); set.setDuration(5000).start();
除此之外,属性动画也可通过XML定义。简单介绍使用的标签及属性。
属性动画定义在res/animator 目录下。
标签<set> 属性 ordering(together/squentially)动画集合中的动画的播放顺序。
标签<objectAnimator> 属性 propertyName 属性名称、durantion 持续时间、valueFrom、valueTo、startOffset (int)延迟时间,repeatCount 重复次数、repeatMode(repeat/reverse)重复模式、valueType(intType/floatType)颜色属性不需指定。
标签<animator> 与<objectAnimator>类似,无propertyName属性。
定义完成后通过以下代码使用属性动画
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this,R.anim.animation_test); set.setTarget(mButton); set.start();
在实际开发中,由于XML定义的方式无法获得属性的初始值,所以一般采用代码的方式使用属性动画。
三、插值器Interpolator和估值器Evaluator
在属性动画中,属性随时间的变化由插值器和估算器共同决定。
1、Interpolator 与View动画中的类似。在属性动画中,Interpolator返回的是属性的改变比例,参数为时间的变化比例。如时间流逝50%时,返回此时属性的变化比例。
2、Evaluator 内部的evaluate方法接受三个参数,fraction、start、end,根据三者计算得到属性值,其中fraction即属性值的变化比例。
自定义插值器实现Interpolator或者TimeInterpolator,自定义估算器则实现TypeEvaluator,如果是对其他类型(除int、float、Color外)做动画,则必须要自定义类型估算算法。
四、对任意属性做动画
属性动画要求动画对象具有属性的get和set方法,其中get方法用于获取属性的起始值,set方法则用于动画执行过程中动态的对属性进行赋值。所以当View无法提供这两个方法或者提供的方法无法对需要的属性进行设置(如Button的setWidth方法)时,就不可以直接使用属性动画(ObjectAnimator)。
未解决上述问题共有三种方法
1、为对象添加get和set方法,该方法对于系统提供的View来说无法实现。
2、用一个类包装原始对象,间接为其提供get和set方法,步骤如下
//包装类,为View提供自定义的get和set方法 private static class ViewWrapper{ private View target ; ViewWrapper(View target){ this.target = target; } public int getWidth(){ return target.getLayoutParams().width; } public void setWidth(int width){ target.getLayoutParams().width = width; target.requestLayout(); } }
3、使用ValueAnimator,上文已介绍。
五、属性动画的工作原理
六、注意事项
1、OOM问题
2、内存泄露
对于属性动画中无限循环的动画需在Activity退出时及时的关闭动画,否则会因Activity无法释放而造成内存泄漏
3、兼容性问题
4、不要使用px
5、动画元素交互
在API11之后,属性动画的效果是可以真实改变View的位置的,而View则只改变影响,所以事件响应会有问题。
6、View动画的问题
由于View动画是对View的影像进行操作,所以有时候会出现动画完成后View无法隐藏的情况,此时只要调用clearAnimation清除动画效果即可。
7、硬件加速
为了系统顺畅,动画效果建议开启硬件加速。