逐帧动画(frame-by-frame animation)
原理:就是把一个完整的动画拆分成一张张单独的图片,然后将它们连贯起来进行播放
补间动画(tweened animation)
原理:对View进行一系列的动画操作,包括淡入淡出、缩放、平移、旋转四种
缺点:
只能作用在View
上,不能对非View对象进行操作,比如说有一个Point对象用于管理坐标,然后我希望通过修改Point,在onDraw()中根据Point来进行绘制。这种对非View对象的操作补间动画就无法实现。只能实现移动、缩放、旋转、淡入淡出这四种动画操作,其实补间动画就是使用
硬编码
的方式来完成的,功能限定死
就是这些,没有扩展性
可言。只改变了View的
显示效果
,而没有
真正改变View的属性(位置)
。
也就是因为以上的几点原因,出现了属性动画
,解决了上述的问题
属性动画(property animation)
原理:是一种不断对值进行操作的机制,并将值赋值到指定对象的指定属性上,可以是任意对象的任意属性
ValueAnimator
对一个值进行平滑的动画过渡,然后你可以添加监听在这个过程中做一些你想做的事情
比如:
ValueAnimator animator = ValueAnimator.ofInt(0,200);
animator.setDuration(2000); //设置持续时间
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int value = (int) valueAnimator.getAnimatedValue();
Log.d("TAG","current value = " + value);
}
});
animator.start();
ValueAnimator animator = ValueAnimator.ofFloat(1f,5f,0f,10f);
animator.setDuration(2000); //设置持续时间
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float value = (float) valueAnimator.getAnimatedValue();
Log.d("TAG","current value = " + value);
}
});
animator.start();
ValueAnimator最常用的应该就是 ofFloat()
和 ofInt()
这两个方法了。
此外还可以调用 setStartDelay()
来设置动画延迟播放的时间
setRepeatCount()
和 setRepeatMode()
方法设置动画循环播放的次数以及循环播放的模式,循环模式包括 RESTART
、
REVERSE
两种:重新播放和倒序播放的意思
ObjectAnimator
与 ValueAnimator 不同的是 ObjectAnimator 可以直接对任意对象的任意属性进行动画操作,比如说View的alpha属性。
不过虽然ObjectAnimator会更常用一些,但它其实是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成(应该在ValueAnimator对一个值进行平滑过渡时,在监听方法内操作View的属性)。
比如:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
animator.setDuration(5000);
animator.start();
或
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
animator.setDuration(5000);
animator.start();
这里的第一个参数传入的是要操作的View,第二个参数是想对该对象的哪个属性进行动画操作。
第二个参数可以传什么样的值呢?
可以传任意值! ObjectAnimator
的工作机制并不是直接对我们传入的属性名
进行操作的,而是会去寻找这个属性名对应的set
、get
方法,所以可以传任意值,只要这个值有set
、get
方法就OK。
组合动画
实现组合动画功能主要借助 AnimatorSet
这个类,这个类提供了一个play()
方法,向这个方法中传入一个Animator对象将会返回一个 AnimatorSet.Builder
的实例, AnimatorSet.Builder
中包含以下四个方法:
after(Animator anim) 将现有动画插入到传入的动画之后执行
after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到传入的动画之前执行
with(Animator anim) 将现有动画和传入的动画同时执行
下面是示例代码,效果是让TextView先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出效果,就可以这样写:
ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);
ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
AnimatorSet animSet = new AnimatorSet();
animSet.play(rotate).with(fadeInOut).after(moveIn);
animSet.setDuration(5000);
animSet.start();
可以看到,这里先是把三个动画对象创建出来,然后new出一个 AnimatorSe
t对象后将这三个动画对象进行播放排序。
Animator监听器
有些时候,我们希望可以监听到动画的各种事件,比如动画何时开始,何时结束,然后在开始或结束的时候去执行一些逻辑,Animator
类中提供了一个addListener()
方法,这个方法接收一个AnimatorListener
,我们只要去实现这个AnimatorListener
就可以监听动画的各种事件了。
因为ObjectAnimator
继承自ValueAnimator
,ValueAnimator
又继承自Animator
,而AnimatorSet
也继承自Animator
,所以addListener()
这个方法算是个通用方法。
ObjectAnimator
、ValueAnimator
、AnimatorSet
都可以使用。
示例代码:
anim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
//动画开始时调用
}
@Override
public void onAnimationEnd(Animator animator) {
//动画结束时调用
}
@Override
public void onAnimationCancel(Animator animator) {
//动画被取消时调用
}
@Override
public void onAnimationRepeat(Animator animator) {
//动画重复执行时调用
}
});
但是有时候我们可能只想监听一个事件,不想监听那么多,要把四个接口全部实现一遍就显得非常繁琐,为此,Android提供了一个适配器类 AnimatorListenerAdapter
使用这个类就可以解决掉实现接口繁琐的问题了,如下:
anim.addListener(new AnimatorListenerAdapter() {
});
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
}
});
这里我们向addListener()方法传入这个适配器对象,由于AnimatorListenerAdapter中已经将每个接口都实现好了,所以这里不用实现任何一个方法也不会报错。那么如果我想监听动画结束这个事件,就只需要单独重写这一个方法就可以了。
使用XML编写动画
使用代码来编写动画是最常用的、也是最方便的做法,但是某些情况我们会需要使用XML来编写动画,比如将某个通用的动画编写到XML里面,就可以在各个界面中轻松去重用它。
首先需要在res目录下新建一个animator文件夹,所有属性动画的XML文件都应该存放在这个文件夹。然后XML文件中一共可以使用三种标签:
对应代码中的ValueAnimator 对应代码中的ObjectAnimator 对应代码中的AnimatorSet
比如我们想实现一个从0到100平滑过渡的动画,可以这样写:
而如果想将一个View的alpha属性从1变0,可以这样写:
另外,XML也可以完成复杂的组合动画,比如上面的那个效果:一个View从屏幕外移动进来,然后旋转360度,旋转同时进行淡入淡出,可以这样写:
最后我们怎么调用XML中的代码呢?
Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);
animator.setTarget(view); //设置动画的作用目标View
animator.start();
参考自:
1、Android属性动画完全解析(上),初识属性动画的基本用法
2、Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法
3、 Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法
Android属性动画深入分析:让你成为动画牛人
Android应用开发之所有动画使用详解
Android动画,一篇就够