Android--Property Animation介绍
来源:互联网 发布:软件项目工作量统计表 编辑:程序博客网 时间:2024/05/19 10:07
1、简介
属性动画是谷歌在Android3.0提出的动画框架,但我们使用以前的动画框架也能实现很丰富的动画效果,比如位移,旋转,缩放,透明度等等,那为什么谷歌还要提出属性动画。
补间动画(Tweened Animations)只能够实现移动、缩放、旋转和淡入淡出这四种动画操作,动画机制就是使用硬编码的方式来完成的,功能限定死就是这些,基本上没有任何扩展性可言。
并且补间动画只能作用于View,而且补间动画改变的只是View的绘制效果,View真正的属性并没有改变。比如,一个ImageView做平移的动画,虽然图片的确做了平移,但ImageView可点击的区域并没随着平移而改变,还是在原来的位置。
可以看到并没有改变 ImageView 的位置,我们还是要在原来的位置才能触发点击效果。所以补间动画并不适合做具有交互的动画效果,只用来做显示型的效果。
而属性动画则可以改变真正的属性,从而实现按钮平移时点击区域也跟着平移。通俗点说,属性动画其实就是在一定时间内,按照一定规律来改变对象的属性,从而使对象展现出动画效果。
属性动画和补间动画一样,可以通过xml文件定义,不同的是,补间动画的xml文件放于res/anim/目录下,而属性动画的xml文件则放于res/animator/目录下。同样的,在Java代码里引用属性动画的xml文件时,则用R.animator.filename,不同于补间动画用R.anim.filename引用。
2、相关API
Property Animation 就是通过动画方式来改变对象的属性来实现我们想要的效果。我们来了解这些相关的属性:
- Duration:动画的持续时间,默认300ms。
- Time interpolation:时间差值,就是Animation中的LinearInterpolator、AccelerateDecelerateInterpolator,是定义动画的变化率。
- Repeat count and behavior:重复次数、以及重复模式;可以定义重复多少次;重复时从头开始,还是反向。
- Animator sets:动画集合,你可以定义一组动画,一起执行或者顺序执行。
- Frame refresh delay:帧刷新延迟,对于你的动画,多久刷新一次帧;默认为10ms,但最终依赖系统的当前状态;基本不用管。
和补间动画的属性设置是一样的,当然最重要的还是熟练掌握这些相关的类:
- ObjectAnimator 动画的执行类
- ValueAnimator 动画的执行类
- AnimatorSet 用于控制一组动画的执行:线性,一起,每个动画的先后执行等。
- AnimatorInflater 用户加载属性动画的xml文件
- TypeEvaluator 类型估值,主要用于设置动画操作属性的值。
- TimeInterpolator 时间插值,上面已经介绍。
总的来说,属性动画就是,动画的执行类来设置动画操作的对象的属性、持续时间,开始和结束的属性值,时间差值等,然后系统会根据设置的参数,动态的变化对象的属性。
3、ObjectAnimator
属性框架中最简单也是最常用的对象就是 ObjectAnimator,它可以直接对任意对象的任意属性进行动画操作。
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
ofFloat 是我们经常使用的 ObjectAnimator 的静态方法,使用它我们可以轻松实现位移,旋转,缩放,透明度变化等多种动画效果。
target :就是我们所要去操纵的一个对象,以上图所展示的,这个对象如果用属性动画,就是 ImageView。
propertyName:顾名思义是属性名字,这个就是我们实现效果的关键,要写入的是我们想要实现的动画,以字符串的形式。常用属性名如下:
- alpha:控制 View 对象的透明度变化
- translationX 和 translationY:作为一种增量来控制View对象从它容器的左上角坐标偏移的位置
- X 和 Y:它们与 translation不同的是,translation是偏移量,而X,Y则是到达的绝对值
- rotation、rotationX 和 rotationY:控制View围绕支点进行2D和3D的旋转
- scaleX 和 scaleY:控制View围绕它的中心点进行缩放
- pivotX 和 pivotY:控制View对象的支点位置,围绕这个支点进行旋转和缩放的处理,默认情况下支点位置为对象的中心点
- backgroundColor:可以对 View 对象的背景色做修改
因为属性动画操控的目标基本上是View对象,所以想要知道更多属性名,可以写个类继承 View,用 set,get看有多少可修改的属性,那些大都可以当propertyName使用。
values:既我们想要做的动画的属性值,这个符合要求下可以是任意个。
1、Alpha
imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ObjectAnimator .ofFloat(imageView, "alpha", 0.1F, 1.0F) .setDuration(500) .start(); }});
用这样的语法一句代码就可以实现动画播放啦,是不是很方便。当然如果想要设置更多属性,也可以去实例对象。
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 0.1f, 1.0f);animator.setDuration(500);animator.setInterpolator(new DecelerateInterpolator());//设置动画插入器,减速animator.setRepeatCount(3);//设置动画重复次数,-1代表无限,这里则播放4次动画animator.setRepeatMode(ValueAnimator.REVERSE);//设置动画循环模式animator.start();
2、Translation
imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ObjectAnimator .ofFloat(imageView, "translationX", -300, 400) .setDuration(500) .start(); }});
因为使用的propertyName是translationX,所以只会做 X坐标上的移动,并且能够看到点击区域的变化,属性动画的确改变了 View对象的位置。
而如果用 X,Y,代码如下:
imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ObjectAnimator.ofFloat(imageView, "X", 200).setDuration(1000).start(); }});
3、Rotation
propertyName 设置为rotation,则做普通的旋转。
imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ObjectAnimator .ofFloat(imageView, "rotation", 0, 360) .setDuration(500) .start(); }});
rotationX 则是将 View 对象绕 X轴旋转,实现3D的旋转,rotationY 则是绕 Y轴旋转。
imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ObjectAnimator .ofFloat(imageView, "rotationY", 0, 360) .setDuration(500) .start(); }});
4、Scale
scaleX,scaleY 也与translation 和 rotation一样,分别只在 X轴和 Y轴上起作用,scaleX,代表纵向的大小不变,在 X轴上进行缩放,scaleY就是相反的效果。
imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ObjectAnimator .ofFloat(imageView, "scaleY", 0, 1) .setDuration(500) .start(); }});
可以看到 View 对象只在Y轴上放大。
5、Pivot
这个属性与我们原来的是一样的,改变中心支点的位置,pivotX 就是只改变支点的 X轴上的坐标,pivotY 则是改变支点的 Y轴上的坐标,这里我先用一下 AnimatorSet 这个类,单单改变支点是没有动画效果的。
imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ObjectAnimator .ofFloat(imageView, "rotation", 0, 360) .setDuration(2000).start(); ObjectAnimator.ofFloat(imageView, "pivotX", 0).start(); }});
可以看到现在的支点 Y轴并没有改变,只是X轴上的坐标变啦。上面我调用了两次ObjectAnimator的静态方法,从结果可以知道这个方法是异步的,所有动画可以同时进行。
PropertyValuesHolder
不过谷歌还给我们提供了一个更好的实现方法,也就是使用PropertyValuesHolder。谷歌在这个类中实现了许多优化,这些优化可以让我们在做多个属性的动画时更有效率,我们来看看代码:
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("rotation", 0, 360F);PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("pivotX", 0);ObjectAnimator .ofPropertyValuesHolder(imageView, p1, p2) .setDuration(2000).start();
最后的结果当然是一样的,这里就不展示啦。
6、BackgroundColor
imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ObjectAnimator.ofInt(imageView, "backgroundColor", Color.RED, Color.BLUE, Color.GRAY, Color.GREEN).start(); }});
这样就很轻松的改变了 View对象的背景色并实现的颜色变化的动画。当然我们的 View是ImageView,所以这时候不把那张图片设置为背景是不会有效果的。
4、AnimatorSet
AnimatorSet 的功能和 PropertyValuesHolder 类似,但 AnimatorSet 可以控制动画播放的顺序,PropertyValuesHolder 更多用于在特定时候为减少代码量而使用。
工欲善其事必先利其器,我们想要熟练地使用组合动画,当然先要了解谷歌给我们都提供了哪些方法。
AnimatorSet 中最重要的方法是play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:
- after(Animator anim) 将现有动画插入到传入的动画之后执行
- after(long delay) 将现有动画延迟指定毫秒后执行
- before(Animator anim) 将现有动画插入到传入的动画之前执行
- with(Animator anim) 将现有动画和传入的动画同时执行
除了play()方法,AnimatorSet 还有个play(Animator… items)方法,可实现任意个动画同时执行,playSequentially(Animator… items)方法按顺序播放动画。
imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ObjectAnimator anim1 = ObjectAnimator.ofFloat(imageView, "scaleX", 0.1F, 1.0F); ObjectAnimator anim2 = ObjectAnimator.ofFloat(imageView, "scaleY", 0.1F, 1.0F); ObjectAnimator anim3 = ObjectAnimator.ofFloat(imageView, "translationX", 0, -300); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(anim1).with(anim2); animatorSet.play(anim3).after(anim1); animatorSet.setDuration(2000); animatorSet.start(); }});
AnimatorSet 同样支持链式写法,但不能随便去连,before(),after()方法都只是对当前动画而言的,也就是play() 里的 Animator。
5、动画监听
对于动画,一般都是一些辅助效果,比如我们要删除个元素,我们可能希望是个淡出的效果,但是最终还是要删掉,并不是透明度没有了,但却还占着位置,所以我们需要知道动画如何结束。
Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。
ObjectAnimator是继承自ValueAnimator的,而ValueAnimator又是继承自Animator的,因此不管是ValueAnimator还是ObjectAnimator都可以使用addListener()这个方法。另外AnimatorSet也是继承自Animator的,因此addListener()这个方法算是个通用的方法。
anim.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animation) { // 会在动画开始的时候调用 } @Override public void onAnimationRepeat(Animator animation) { // 会在动画重复执行的时候调用 } @Override public void onAnimationEnd(Animator animation) { // 会在动画结束的时候调用 } @Override public void onAnimationCancel(Animator animation) { // 会在动画被取消的时候调用 } });
animator还有 cancel() 和 end() 方法,cancel动画立即停止,停在当前的位置;end动画直接到最终状态。
但是很多时候我们并不想要监听那么多个事件,可能我们只想要监听动画结束这一个事件,那么每次都要将四个接口全部实现一遍就显得非常繁琐。为此Android提供了一个适配器类,叫作AnimatorListenerAdapter,使用这个类就可以解决掉实现接口繁琐的问题了,如下所示:
anim.addListener(new AnimatorListenerAdapter() { });
我们向addListener()方法中传入这个适配器对象,由于AnimatorListenerAdapter中已经将每个接口都实现好了,所以这里不用实现任何一个方法也不会报错。那么如果我想监听动画结束这个事件,就只需要单独重写这一个方法就可以了,这个大家自己试试就行啦。
现在让我们做一个去除 ImageView 的动画:
imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ObjectAnimator anim1 = ObjectAnimator.ofFloat(imageView, "scaleX", 1.0F, 0.1F); ObjectAnimator anim2 = ObjectAnimator.ofFloat(imageView, "scaleY", 1.0F, 0.1F); ObjectAnimator anim3 = ObjectAnimator.ofFloat(imageView, "alpha", 1.0f, 0.0f); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(anim1, anim2, anim3); animatorSet.setDuration(2000); animatorSet.start(); animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { ViewGroup parent = (ViewGroup) imageView.getParent(); if (parent != null) parent.removeView(imageView); } }); }});
代码很简单,就不解释啦,直接看效果吧。
可以看到在做完动画后,怎么点击都没有反应,因为这个时候 ImageView 已经被移除啦。
除了addListener添加监听器外,还有一种 addUpdateListener 监听器。
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { }});
该方法用来监听动画绘制过程中的每一帧的改变,通过这个方法,我们可以在动画重绘的过程中,实现自己的逻辑。
6、ValueAnimator
ValueAnimation 是 ObjectAnimator 的父类,我们前面介绍的 ObjectAnimator 可以作用于某一个控件的某个属性,但 ValueAnimator 本身并不会作用于任何一个属性,也不会启动任何一个动画,它就相当于一个数值发生器,它可以产生我们想要的任何数值。
Android 系统给 ValueAnimator 提供了很多计算数值的方法,如 int,float,point等等,同时我们也可以根据自己的需要自定义计算数值的方法。
那我们产生这些数值有什么用呢?在属性动画中,实现每一步的动画效果,都是通过 ValueAnimator 计算出来的,比如我们要实现一个0 到 100的位移动画,随着动画的执行,它整个的值也会在0到100进行递增。我们有了这些值就可以作用于我们的属性,让它产生一个动画效果,那 ValueAnimator 是怎么去产生这些值的呢?
首先,ValueAnimator 会根据动画已进行的时间与它持续的总时间的比值产生一个0到1的时间因子,有了这样一个值经过相应的变换,就可以根据我们的 startValue 和 endValue(也就是初始值和结束值)来生成中间的相应值。同时,通过插值器的使用,我们还可以进一步的控制每个时间因子,它产生值的变化速度,如果我们使用 LinearInterpolator,那它生成值的时候就会是一个线性变化,只要时间相同,它的增量也相同。
由于 ValueAnimator 并不响应于任何一个动画,也不能控制任何一个属性,所以它并没有 ObjectAnimator 使用的广泛。
imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ValueAnimator animator = ValueAnimator.ofFloat(-300, 300, 0, 200); animator.setTarget(imageView); animator.setDuration(1000).start(); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { imageView.setTranslationY((Float)animation.getAnimatedValue()); } }); }});
这里就用到我们上面提到的 addUpdateAnimation,因为是监听动画绘制过程中的每一帧的改变,所以我们把 ValueAnimator 当前产生的值不断地传进去重绘,这样就实现了位移的效果,其它动画也是如此。
如果你把取得的值用 Log 日志打印出来,就会发现值在1000毫秒的时间内从-300平滑过渡到了300,再过渡到0,最后到200。
ValueAnimator 同样可以调用setStartDelay()方法来设置动画延迟播放的时间,还有setRepeatCount()和setRepeatMode()等方法,这些各种动画都是通用的。
7、Xml配置
Xml的配置和使用大都是标签上的应用,我就不在这里作介绍啦,有兴趣的朋友可以看我的博客Android–Animation标签介绍。
关于Property Animation的基本介绍就到这里啦,属性动画还有很多高级的使用,像TypeValue,Evaluator,这些我在其它的博客中会再介绍的。
结束语:本文仅用来学习记录,参考查阅。
- Android--Property Animation介绍
- Android 属性动画(Property Animation)介绍
- Android -animation-Property Animation
- Android Animation学习(一) Property Animation介绍
- Android Animation学习(一) Property Animation介绍
- Android Animation学习(一) Property Animation介绍
- Android开发之Animation介绍(下) ——Property Animation
- Android Animation学习(一) Property Animation介绍
- Android 动画学习(二)之Property Animation初步介绍
- Android 动画学习(二)之Property Animation初步介绍
- android的属性动画Property Animation介绍及其使用
- android属性动画(property animation)使用介绍
- Android 动画学习(二)之Property Animation初步介绍
- Android Property Animation动画
- Android Property Animation动画
- Android中的Property Animation
- Android Property Animation
- Android Property Animation示例
- 使用java实现数据库编程
- Linux常用命令--常更
- Codeforces 580C Kefa and Park 题解
- JavaScript排序算法系列——冒泡排序
- zookeeper windows 入门安装和测试
- Android--Property Animation介绍
- UFEI/linux系统加载过程
- Hadoop2.4的ResourceManager HA高可用配置
- 三星I909破解使用GPRS上网教程
- tensorflow之CNN
- dos在windows命令失效
- 练习
- java中Class对象详解和类名.class, class.forName(), getClass()区别
- 电商网站HTTPS实践之路(三)——性能优化篇