属性动画
(一)、属性动画概念:
属性动画,这个是在Android 3.0中才引进的。Property Animation故名思议就是通过动画的方式改变对象的属性.属性动画更改的是对象的实际属性,在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变。可以将属性动画理解为增强版的补间动画。
比如无论如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。而在Property Animation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。
Property Animation不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。
(二)为什么引入属性动画
Android3.0之前提供的补间动画机制还算相对比较健全的,比如你的需求中只需要对View进行移动、缩放、旋转和淡入淡出的操作,那么补间动画已经足够健全了。但是,如果一旦需求超出了这四种操作,补间动画就无能为力了。
例如,我们需要改变View的宽度,这个时候就不能通过补间动画实现。此外,补间动画还有一个最大的缺陷,就是它只是改变了View的显示效果而已,并不会真正的改变View的属性。具体来说,例如屏幕左上角有一个Button,使用补间动画将其移动到右下角,此刻你去点击右下角的Button,它是绝对不会响应点击事件的,因此其作用区域依然还在左上角。只不过是补间动画将其绘制在右下角而已。
(三)、属性动画常用属性:
Duration动画的持续时间,默认300ms。android:duration属性(对应的xml文件)
Time interpolation:时间插值。LinearInterpolator、AccelerateDecelerateInterpolator,定义动画的变化率。android:interpolator属性
Repeat count and behavior:重复次数、以及重复模式;可以定义重复多少次;重复时从头开始(restart),还是反向(reverse)。android:repeatCount属性(可以是整数也可以是infinite(无限))android:repeatMode="restart"
Animator sets: 动画集合,你可以定义一组动画,一起执行或者顺序执行。<set/>,该元素的android:ordering属性指定该组动画是按次序播放还是同时播放。有两个值(sequentially和together分别表示先后执行和同步执行)
Frame refresh delay:帧刷新延迟(帧刷新频率,每个多久播放一帧);默认为10ms,但最终依赖系统的当前状态。
(三)、属性动画API:相关的类
ObjectAnimator 动画的执行类(是ValueAnimator的子类,使用简单常用。少数场景下,由于其存在一些限制,再考虑使用ValueAnimator)
ValueAnimator 动画的执行类
AnimatorSet 用于控制一组动画的执行:线性,一起,每个动画的先后执行等。
AnimatorInflater 用户加载属性动画的xml文件
TypeEvaluator 类型估值,主要用于设置动画操作属性的值。
TimeInterpolator 时间插值
总的来说,属性动画就是,动画的执行类来设置动画操作的对象的属性、持续时间,开始和结束的属性值,时间差值等,然后系统会根据设置的参数动态的变化对象的属性。
属性动画,这个是在Android 3.0中才引进的。Property Animation故名思议就是通过动画的方式改变对象的属性.属性动画更改的是对象的实际属性,在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变。可以将属性动画理解为增强版的补间动画。
比如无论如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。而在Property Animation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。
Property Animation不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。
(二)为什么引入属性动画
Android3.0之前提供的补间动画机制还算相对比较健全的,比如你的需求中只需要对View进行移动、缩放、旋转和淡入淡出的操作,那么补间动画已经足够健全了。但是,如果一旦需求超出了这四种操作,补间动画就无能为力了。
例如,我们需要改变View的宽度,这个时候就不能通过补间动画实现。此外,补间动画还有一个最大的缺陷,就是它只是改变了View的显示效果而已,并不会真正的改变View的属性。具体来说,例如屏幕左上角有一个Button,使用补间动画将其移动到右下角,此刻你去点击右下角的Button,它是绝对不会响应点击事件的,因此其作用区域依然还在左上角。只不过是补间动画将其绘制在右下角而已。
(三)、属性动画常用属性:
Duration动画的持续时间,默认300ms。android:duration属性(对应的xml文件)
Time interpolation:时间插值。LinearInterpolator、AccelerateDecelerateInterpolator,定义动画的变化率。android:interpolator属性
Repeat count and behavior:重复次数、以及重复模式;可以定义重复多少次;重复时从头开始(restart),还是反向(reverse)。android:repeatCount属性(可以是整数也可以是infinite(无限))android:repeatMode="restart"
Animator sets: 动画集合,你可以定义一组动画,一起执行或者顺序执行。<set/>,该元素的android:ordering属性指定该组动画是按次序播放还是同时播放。有两个值(sequentially和together分别表示先后执行和同步执行)
Frame refresh delay:帧刷新延迟(帧刷新频率,每个多久播放一帧);默认为10ms,但最终依赖系统的当前状态。
(三)、属性动画API:相关的类
ObjectAnimator 动画的执行类(是ValueAnimator的子类,使用简单常用。少数场景下,由于其存在一些限制,再考虑使用ValueAnimator)
ValueAnimator 动画的执行类
AnimatorSet 用于控制一组动画的执行:线性,一起,每个动画的先后执行等。
AnimatorInflater 用户加载属性动画的xml文件
TypeEvaluator 类型估值,主要用于设置动画操作属性的值。
TimeInterpolator 时间插值
总的来说,属性动画就是,动画的执行类来设置动画操作的对象的属性、持续时间,开始和结束的属性值,时间差值等,然后系统会根据设置的参数动态的变化对象的属性。
ValueAnimator
ValueAnimator是整个属性动画机制当中最核心的一个类,前面我们已经提到了,属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等,确实是一个非常重要的类。
ValueAnimator 常用方法:
1、ofFloat()小数位的动画过渡
2、ofInt()整数位的动画过度
3、ofObject()
4、setStartDelay()动画播放延迟时间
5、setRepeatCount()动画循环次数
6、setRepeatMode()循环模式:RESTART和REVERSE是重新播放和倒叙播放
valuseAnimator的使用比较简单,可以是一个单一的过渡,没有界面效果:
ValueAnimator 常用方法:
1、ofFloat()小数位的动画过渡
2、ofInt()整数位的动画过度
3、ofObject()
4、setStartDelay()动画播放延迟时间
5、setRepeatCount()动画循环次数
6、setRepeatMode()循环模式:RESTART和REVERSE是重新播放和倒叙播放
valuseAnimator的使用比较简单,可以是一个单一的过渡,没有界面效果:
private void ValueTest(View view){
//将值从0过度到1
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
//可以设置多个这样就是从0到1再到0.5
//ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f,0.5f);
anim.setDuration(300);
anim.start();
}
但是这样无法知道他是否是执行了,可以通过添加一个动画的监听器来监听他的回调,利用addUpdateListener()方法:
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentValue = (float) animation.getAnimatedValue();
Log.e("ceshi", "cuurent value is " + currentValue);
}
});
将结果打印出来可以看到
ValueAnimator确实已经在正常工作了,值在300毫秒的时间内从0平滑过渡到了1。
也可以调用setStartDelay()设置动画延时播放的时间,和setRepeatCount()循环次数和setRepeatMode()循环模式
ObjectAnimator
相比于ValueAnimator,ObjectAnimator可能才是我们最常接触到的类,因为ValueAnimator只不过是对值进行了一个平滑的动画过渡,但我们实际使用到这种功能的场景好像并不多。而ObjectAnimator则就不同了,它是可以直接对任意对象的任意属性进行动画操作的,比如说View的alpha属性。
不过虽说ObjectAnimator会更加常用一些,但是它其实是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成的,因此ValueAnimator仍然是整个属性动画当中最核心的一个类。那么既然是继承关系,说明ValueAnimator中可以使用的方法在ObjectAnimator中也是可以正常使用的,它们的用法也非常类似。
如果想将图片在3000毫秒内变成半透明再还原,可以这么写:
不过虽说ObjectAnimator会更加常用一些,但是它其实是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成的,因此ValueAnimator仍然是整个属性动画当中最核心的一个类。那么既然是继承关系,说明ValueAnimator中可以使用的方法在ObjectAnimator中也是可以正常使用的,它们的用法也非常类似。
如果想将图片在3000毫秒内变成半透明再还原,可以这么写:
//它是可以直接对任意对象的任意属性进行动画操作的
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f, 1f);
animator.setDuration(2000);
//设置循环次数
animator.setRepeatCount(2);
//设置循环方式
animator.setRepeatMode(ValueAnimator.RESTART);
animator.start();
这里ofFloat()内的参数中第一个需要传入一个object对象,就是需要动画实现的对象;
第二个参数是想对对象的那个属性进行动画操作;
第三个和以后的参数与ValueAnimator一致;
实现效果如下:
还可以按照一样的思路实现旋转缩放和移动
旋转代码:
旋转代码:
//设置旋转
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotation", 0f,360f);
animator.setDuration(2000);
animator.start();
缩放代码:
//设置缩放
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "scaleX", 1.0f,0.5f,1.0f);
animator.setDuration(2000);
animator.start();
移动代码:
//设置移动
//获取图片当前位置
float initialX = myImageView.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", initialX,-200,initialX);
animator.setDuration(5000);
//设置动画插入器
animator.setInterpolator(new AccelerateInterpolator());
animator.start();
效果如下:
设置了动画插入器横向移动的时候先慢后快。
比较重要的是:
//ObjectAnimator.ofFloat第二个参数可以放置任意的值,其中(alpha、rotation、translationX、translationY和scaleY、scaleX这几个值,分别可以完成淡入淡出、旋转、水平或垂直移动、垂直或水平缩放缩放这几种动画)
组合动画
独立的动画能够实现的视觉效果毕竟是相当有限的,因此将多个动画组合到一起播放就显得尤为重要。幸运的是,Android团队在设计属性动画的时候也充分考虑到了组合动画的功能,因此提供了一套非常丰富的API来让我们将多个动画组合到一起。
实现组合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:
after(Animator anim) 将现有动画插入到传入的动画之后执行
after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到传入的动画之前执行
with(Animator anim) 将现有动画和传入的动画同时执行
先整体缩放再淡入淡出,效果如下:
实现组合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:
after(Animator anim) 将现有动画插入到传入的动画之后执行
after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到传入的动画之前执行
with(Animator anim) 将现有动画和传入的动画同时执行
先整体缩放再淡入淡出,效果如下:
代码实现:
1、利用AnimatorSet实现组合动画,这个是最丰富的可以实现动画前后顺序的处理
1、利用AnimatorSet实现组合动画,这个是最丰富的可以实现动画前后顺序的处理
//利用AnimatorSet实现组合动画,这个是最丰富的可以实现动画前后顺序的处理
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.5f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.5f);
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(view, "alpha", 1f, 0.5f);
AnimatorSet animSet = new AnimatorSet();
animSet.play(scaleXAnim).with(scaleYAnim).before(alphaAnim);
animSet.setDuration(3000);
animSet.start();
2、利用动画刷新监听实现组合动画,第二个参数随便写,只能一起执行
//利用动画刷新监听实现组合动画,第二个参数随便写,只能一起执行
ObjectAnimator anim = ObjectAnimator.ofFloat(view,"lw",1.0f,0.0f,1f);
anim.setDuration(5000);
anim.start();
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float cVal = (Float) animation.getAnimatedValue();
view.setAlpha(cVal);
view.setScaleX(cVal);
view.setScaleY(cVal);
}
});
3、除了上面Animator类还可以使用PropertyValuesHolder类来实现组合动画,
不过这个组合动画就没有上面的丰富了,使用PropertyValuesHolder类只能多个动画一起执行。
当然我们得结合 ObjectAnimator.ofPropertyValuesHolder(Object target,PropertyValuesHolder… values);
方法来使用。第一个参数是动画的目标对象,之后的参数是PropertyValuesHolder类的实例,可以有多个这样的实例。代码如下:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY, pvhZ).setDuration(5000).start();
在很多时候,我们希望可以监听到动画的各种事件,比如动画何时开始,何时结束,然后在开始或者结束的时候去执行一些逻辑处理。这个功能是完全可以实现的,Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。
大家已经知道,ObjectAnimator是继承自ValueAnimator的,而ValueAnimator又是继承自Animator的,因此不管是ValueAnimator还是ObjectAnimator都是可以使用addListener()这个方法的。另外AnimatorSet也是继承自Animator的,因此addListener()这个方法算是个通用的方法。
添加一个监听器的代码如下所示:
大家已经知道,ObjectAnimator是继承自ValueAnimator的,而ValueAnimator又是继承自Animator的,因此不管是ValueAnimator还是ObjectAnimator都是可以使用addListener()这个方法的。另外AnimatorSet也是继承自Animator的,因此addListener()这个方法算是个通用的方法。
添加一个监听器的代码如下所示:
private void AnimatorListener(View view){
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotation", 0f,360f);
animator.setDuration(2000);
//第一种监听方式
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
Log.e("ceshi", "Start");
}
@Override
public void onAnimationEnd(Animator animator) {
Log.e("ceshi", "End");
}
@Override
public void onAnimationCancel(Animator animator) {
Log.e("ceshi", "Cancel");
}
@Override
public void onAnimationRepeat(Animator animator) {
Log.e("ceshi", "Repeat");
}
});
animator.start();
animator.setRepeatCount(2);
}
第二种监听方式,利用Android提供了一个适配器类,叫作AnimatorListenerAdapter实现动画的监听,代码如下:
//第二种方式,可以自定义加载监听事件,利用适配器
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
});
可以自定义监听的方法,需要什么就写什么。
日志打印结果:
使用XML编写属性动画
通过XML来编写动画可能会比通过代码来编写动画要慢一些,但是在重用方面将会变得非常轻松,比如某个将通用的动画编写到XML里面,我们就可以在各个界面当中轻松去重用它。
如果想要使用XML来编写动画,首先要在res目录下面新建一个animator文件夹,所有属性动画的XML文件都应该存放在这个文件夹当中。然后在XML文件中我们一共可以使用如下三种标签:
<animator> 对应代码中的ValueAnimator
<objectAnimator> 对应代码中的ObjectAnimator
<set> 对应代码中的AnimatorSet
所有的都只需调用xml文件就好:
如果想要使用XML来编写动画,首先要在res目录下面新建一个animator文件夹,所有属性动画的XML文件都应该存放在这个文件夹当中。然后在XML文件中我们一共可以使用如下三种标签:
<animator> 对应代码中的ValueAnimator
<objectAnimator> 对应代码中的ObjectAnimator
<set> 对应代码中的AnimatorSet
所有的都只需调用xml文件就好:
ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(getApplicationContext(),R.animator.object_animator);
animator.setTarget(view);
animator.start();
ValueAnimator:
valueFrom和valueTo分别是起始和终止的数值,valueType对应着ofFloat等;
<!--valueType对应着ofFloat ofInt ofObject-->
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="0"
android:valueTo="100"
android:valueType="floatType"/>
ObjectAnimator:
其中propertyName是参数值可以是alpha也可以是scaleX等,跟java代码实现差不多
<objectAnimator android:valueFrom="1"
android:valueTo="0.5"
android:valueType="floatType"
android:propertyName="alpha"
xmlns:android="http://schemas.android.com/apk/res/android" />
组合动画:
ordering 有两个选项:sequentially 和 together 。其中 together 为默认项。
sequentially 表示 set 中的动画,按照先后顺序逐步进行(a 完成之后进行 b )。
together 表示set 中的动画,在同一时间同时进行。
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially" >
<!--ordering 有两个选项:sequentially 和 together 。其中 together 为默认项。
sequentially 表示 set 中的动画,按照先后顺序逐步进行(a 完成之后进行 b )。
together 表示set 中的动画,在同一时间同时进行。-->
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="-200"
android:valueTo="200"
android:valueType="floatType" >
</objectAnimator>
<set android:ordering="together" >
<objectAnimator
android:duration="3000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" >
</objectAnimator>
<set android:ordering="sequentially" >
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType" >
</objectAnimator>
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" >
</objectAnimator>
</set>
</set>
</set>
效果与java代码相同。
参考了大神的博客:http://blog.csdn.net/guolin_blog/article/details/43536355
源码: 下载