android属性动画概述
一 、概要:
动画的英文有很多表述,如animation、cartoon、animated cartoon、cameracature。其中较正式的 “Animation” 一词源自于拉丁文字根anima,意思为“灵魂”,动词animate是“赋予生命”的意思,引申为使某物活起来的意思。所以动画可以定义为使用绘画的手法,创造生命运动的艺术。(摘自百科)
画技术较规范的定义是采用逐帧拍摄对象并连续播放而形成运动的影像技术。不论拍摄对象是什么,只要它的拍摄方式是采用的逐格方式,观看时连续播放形成了活动影像,它就是动画。(摘自百科)
我对电子设备上动画狭义的理解就是模拟(记录)并展现,任何事物运动或存在的过程(不要纠结。。。。)。由此可知道任何动画的实现都离不开,动画起点,动画终点,运动轨迹,持续时间,速度变化率这几个要素。
android提供了三种实现动画的方式,其中系统框提供的是属性动画(Property Animation 3.0以上),补间动画(View animation),除了前两种方式,还有一种drawable动画(帧动画,动态设置drawable图片,而呈现的动画)。
二 、属性动画特点:
1、 属性动画系统,是通过动态修改对象(view ,或其他对象产生数据逐渐变化)的属性,而产生的具有真正意义的动画,相对传统的补间动画真正做到了动态逐渐修改view的大小或位置,包括那些不被渲染到屏幕上的对象。该系统是可扩展的,可以自定义属性动画类型。
android 属性动画可以通过修改duration(android 系统默认300ms)属性,来改变动画的持续时间,可以通过修改repeat属性来改变动画的重复次数,通过修改behavior属性来改变动画的重复动画时的策略(反向,正常);此外属性动画你可以通过Animator sets,一次对一个对象(view),进行多种动画,这个动画集,可以同时进行,也可以按某个你指定的顺序进行。
由概述中我们知道任何动画其实都可以简化成物理学中物体移动过程的描述。下面用谷歌文档的几个图来描述一下属性动画的工作。
(1)
上图可以简化为物理学物体的一次匀速运动。
(2)
上图可以简化为物理学物体的一次匀加速移动
由以上两张图我们对android 属性动画有了一个初步的了解,下面我们再通过第三张图来看一下,android 属性动画的具体接口类的相互关系及工作原理
(3)
有第三张图可以看出,一个属性动画会包括时间插值器属性,类型评估属性,持续时间属性,属性开始点,属性结束点。此外还包括一个开启动画的start方法。
就属性动画中的valueAnimator 来概述动画的过程,就是先生成一个valueAnimator对象,然后调用start方法开启,然后会以当前时间点duration时间差,配合TimeInterpolator生成一个系数(0-1),然后再通过StartPropertyValue到endPropertyValue配合TypeEvaluator,计算出一个当前PropertyValue,然后调用动画更新接口,将该值进行更新。此动画之所以能持续演进,归根到底为因为硬件电子时钟为触发点。结束点也是通过duration来结束。
其实动画思想,说简单了就是,单位时间对应某个对象属性的一 一映射。
属性动画与view animation 相比,更加灵活,属性动画可以对任何对象进行动画操作(所谓动画操作,笔者认为,就是在duration时间内,动态获取一组属性数据(属性起点到结束带点)),而view animation 只能作用在view的某些属性上,列入旋转,平移等。
此外属性动画相比view animation来说是真正改变了动画对象的属性值,而view animation 只是改变了view 对象的渲染(ondraw)位置。其真正的属性没有改变。举个简单的例子,通过属性动画将一个button 从手机屏幕最上面移动到屏幕最下边,如果对button 加入点击事件则只有点击动画后的位置(button所见)可以监听到,若对该button平移如果采用的是补间动画,点击移动位置,无响应事件,而只有点击移动前的位置,才能监听到。
属性动画相比view animation takes less time to setup and requires less code to write.(摘自官方文档),官方提倡如果用viwe animation 能满足你的需求,是没必要一定用属性动画来实现的。
三 、属性动画常用api
1、android 属性动画框架常用类
ValueAnimator : 该类为android.animation.Animator, 用来动态获取一些属性值。可以通过该类实现对各种对象的动画操作。
ObjectAnimator: 该类为ValueAnimator的子类,使用该类操作动画,被操作对象一定要有相应属性值的set方法。
AnimatorSet :该类为 android.animation.Animator的子类,该类提供了一种操作多个动画的机制,可以同时,按一定顺序操作一系列动画。
TypeEvaluator:该接口定义了一个计算值的方法,用来操作计算属性值的类型和方式,android系统提供的实现类ArgbEvaluator,ArgbEvaluator, FloatArrayEvaluator, FloatEvaluator, IntArrayEvaluator, IntEvaluator, PointFEvaluator, RectEvaluator。
TimeInterpolator:时间插值器接口,该接口定义了一个计算获取插值的方法,android系统提供的实现类 AccelerateDecelerateInterpolator, AccelerateInterpolator, AnticipateInterpolator, AnticipateOvershootInterpolator, BaseInterpolator, BounceInterpolator, CycleInterpolator, DecelerateInterpolator, FastOutLinearInInterpolator, FastOutSlowInInterpolator, Interpolator, LinearInterpolator, LinearOutSlowInInterpolator, OvershootInterpolator, PathInterpolator
2、属性动画的简单使用:
valueAnimator:
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.start();
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();
以上两种动画只是动态的计算属性值,如第一种就是1000ms内获取(0-1)直间的值,第二个是1000ms 内获取一个自定义的属性值。实际运用会通过监听Animation Listeners.获取该属性值。做进一步自己想做的。
ObjectAnimator :
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();
通过改动画可以实现foo对象的alpha值的改变,如果foo是个view则会进行透明度变化的动画。(该类型动画,操作动画的对象一定要有第二个参数对应的set方法才会有效)
ObjectAnimator.ofFloat(targetObject, "propName", 1f)
对于该种构造方法,需要操作对象具有第二个参数的set和get方法,才能有效果。
AnimatorSet:
是一个按一定规则操作多个动画的类;列如谷歌官方给的例子核心代码:
ValueAnimator bounceAnim = ObjectAnimator.ofFloat(newBall, "y", startY, endY);
bounceAnim.setDuration(duration);
bounceAnim.setInterpolator(new AccelerateInterpolator());
ValueAnimator squashAnim1 = ObjectAnimator.ofFloat(newBall, "x", newBall.getX(),
newBall.getX() - 25f);
squashAnim1.setDuration(duration/4);
squashAnim1.setRepeatCount(1);
squashAnim1.setRepeatMode(ValueAnimator.REVERSE);
squashAnim1.setInterpolator(new DecelerateInterpolator());
ValueAnimator squashAnim2 = ObjectAnimator.ofFloat(newBall, "width", newBall.getWidth(),
newBall.getWidth() + 50);
squashAnim2.setDuration(duration/4);
squashAnim2.setRepeatCount(1);
squashAnim2.setRepeatMode(ValueAnimator.REVERSE);
squashAnim2.setInterpolator(new DecelerateInterpolator());
ValueAnimator stretchAnim1 = ObjectAnimator.ofFloat(newBall, "y", endY,
endY + 25f);
stretchAnim1.setDuration(duration/4);
stretchAnim1.setRepeatCount(1);
stretchAnim1.setInterpolator(new DecelerateInterpolator());
stretchAnim1.setRepeatMode(ValueAnimator.REVERSE);
ValueAnimator stretchAnim2 = ObjectAnimator.ofFloat(newBall, "height",
newBall.getHeight(), newBall.getHeight() - 25);
stretchAnim2.setDuration(duration/4);
stretchAnim2.setRepeatCount(1);
stretchAnim2.setInterpolator(new DecelerateInterpolator());
stretchAnim2.setRepeatMode(ValueAnimator.REVERSE);
ValueAnimator bounceBackAnim = ObjectAnimator.ofFloat(newBall, "y", endY,
startY);
bounceBackAnim.setDuration(duration);
bounceBackAnim.setInterpolator(new DecelerateInterpolator());
// Sequence the down/squash&stretch/up animations
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
// Fading animation - remove the ball when the animation is done
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
balls.remove(((ObjectAnimator)animation).getTarget());
}
});
// Sequence the two animations to play one after the other
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
// Start the animation
animatorSet.start();
改动画执行可以实现随着手指移动一个跳动的小球,具体运行代码见:
总结:以上只是对动画的理解和简单试例,在后续篇章会继续深入。