现在隆重介绍Android动画中无所不能的属性动画登场,先看看官方文档对属性动画的介绍:
The property animation system is a robust framework that allows you to animate almost anything. You can define an animation to change any object property over time, regardless of whether it draws to the screen or not. A property animation changes a property's (a field in an object) value over a specified length of time. To animate something, you specify the object property that you want to animate, such as an object's position on the screen, how long you want to animate it for, and what values you want to animate between.
是不是很牛逼。。。确实很牛逼,翻译过来的意思大概是(英语比较挫,翻译不对的大家指正):属性动画是一个能为所有事情添加动画的非常健壮的框架,可以通过控件的任意属性,实现控件对话(算了,翻译不下去了),下面开始搞起。首先说明一点,动画原理什么滴,这里就不多讲了,网上有很多,大家可以去官网开说明:http://developer.android.com/guide/topics/graphics/prop-animation.html#value-animator,我就只讲讲如何使用,使用最重要嘛。如果想看中文的话,请看AngelDevi的一篇文章,http://www.cnblogs.com/angeldevil/archive/2011/12/02/2271096.html,根据这篇文章你应该了解属性动画是如何工作的。
(1)写一个属性动画需要准备哪些工作?
Android属性动画开始需要准备 TimeInterpolator、TypeEvaluator。
TimeInterpolator是用来定义插值器的,下表列出Android的几种插值器,可以根据自己的需求,选择不同的插值器。更加详尽的阐述请见http://my.oschina.net/banxi/blog/135633
AccelerateInterpolator | 一开始很慢,然后逐渐加速 |
DecelerateInterpolator | 一开始很快,然后逐渐减速 |
AccelerateDecelerateInterpolator | 变化率开始慢,然后从中间开始加速,然后再减速 |
LinearInterpolator | 线性插值器,匀速 |
BounceInterpolator | 弹跳插值器,类似与小球落到地面弹跳得效果,自行脑补 |
AnticipateInterpolator | 回荡秋千插值器 |
AnticipateOverShotInterpolator | 它开始向上推,然后向下荡,荡过最低线。然后再回到最低线 |
CycleInterpolator | 正弦周期变化插值器 |
OverShotInterpolator |
TypeEvaluator:ValueAnimator根据动画已进行的时间跟动画总时间(duration)的比计算出一个时间因子(0~1),然后根据TimeInterpolator计算出另一个因子,最后TypeAnimator通过这个因子计算出属性值,如上例中10ms时:
首先计算出时间因子,即经过的时间百分比:t=10ms/40ms=0.25经插值计算(inteplator)后的插值因子:大约为0.15,上述例子中用了AccelerateDecelerateInterpolator,计算公式为(input即为时间因子):
(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
最后根据TypeEvaluator计算出在10ms时的属性值:0.15*(40-0)=6pixel。上例中TypeEvaluator为FloatEvaluator,计算方法为 :
public Float evaluate(float fraction, Number startValue, Number endValue) { float startFloat = startValue.floatValue(); return startFloat + fraction * (endValue.floatValue() - startFloat); }
参数分别为上一步的插值因子,开始值与结束值。大家可能对fraction理解有偏差,按照字面意思fraction是片段的意思,这个片段并不是时间片段,而是相当于任务完成的百分比。
(2)开始做一个属性动画
代码1:
private void performAnimate(final View target, final int start, final int end) { //定义一个属性动画,并定义初始值和结束值 ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100); //为属性动画添加监听事件 valueAnimator.addUpdateListener(new AnimatorUpdateListener() { //持有一个IntEvaluator对象,方便下面估值的时候使用 private IntEvaluator mEvaluator = new IntEvaluator(); @Override public void onAnimationUpdate(ValueAnimator animator) { //获得当前动画的进度值,整型,1-100之间 int currentValue = (Integer)animator.getAnimatedValue(); Log.d(TAG, current value: + currentValue); //计算当前进度占整个动画过程的比例,浮点型,0-1之间 float fraction = currentValue / 100f; //这里我偷懒了,不过有现成的干吗不用呢 //直接调用整型估值器通过比例计算出宽度,然后再设给Button target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end); target.requestLayout(); } }); valueAnimator.setDuration(5000).start(); } //按钮点击时,触发动画 @Override public void onClick(View v) { if (v == mButton) { performAnimate(mButton, mButton.getWidth(), 500); } }
上述代码当中并没有使用插值器,因为他自己实现了一个插值器功能,原因在与插值器的作用是计算任务完成量,但是这段代码中是自己计算的,是线性插值。
代码2:
ValueAnimator scan_anim = ValueAnimator.ofInt(30, 2*RADIUS-30); scan_anim.setInterpolator(new LinearInterpolator()); scan_anim.setRepeatCount ( Integer.MAX_VALUE ); scan_anim.setRepeatMode (ValueAnimator.REVERSE); scan_anim.addUpdateListener(new AnimatorUpdateListener() { private IntEvaluator mEvaluator = new IntEvaluator(); @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { // TODO Auto-generated method stub //计算结果 scan_y = (Integer) valueAnimator.getAnimatedValue(); invalidate(); } }); scan_anim.setDuration(800); scan_anim.start();
属性动画流程图如下:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。