这里接上一篇博客:http://blog.csdn.net/sunzhishuai/article/details/52863476 继续来说说android 动画,在上一篇博客中主要讲了android 动画的一些基本使用技巧,这里继续。
(一) Interpolator 的使用插值器的使用
所谓的插值器,就是根据动画时间的流失,来计算当前属性变化的百分比,android 已经实现了几种插值器,如AnticipateInterpolator ,LineInterpolator,效果这里就不说了,大家可以自己试验一下。什么叫根据动画时间的流失,来计算当前属性变化的百分比呢?这里看代码,我自定义了一个插值器,方法很简单实现Interpolator 接口即可。实现getinterpolation 方法。
public class MyInterpolator implements android.view.animation.Interpolator { @Override public float getInterpolation(float input) { return 0; } }
这里就一个参数 input 它的值由系统来给在[0,1] 之间。可以看到我返回的值为0;下面就使用这个插值器,代码如下:
mgirl = (ImageView) findViewById(R.id.iv_girl); ObjectAnimator translationX = ObjectAnimator.ofFloat(mgirl, "TranslationX", 0, 500); translationX.setDuration(2000).setInterpolator(new MyInterpolator()); translationX.start();
一个简单的平移动画,你会发现如果为们运行的话,是没有任何效果的,因为虽然系统根据时间流逝,input 不断变化,但是我们返回0的话 表示我们这个值始终不变啊,所以没有效果,那么如果我们不=直接把input 返回,你会发现根线性插值器是一样的效果。说到这你可能有点感觉了,就是把时间进行了多少的百分百,转换成属性变化的百分比嘛,对,插值器就是这么简单。 但是半分比自然是小于1咯,如果你大于1了,当然可以,单是灰出现,动画属性变化非常大,超出了我们设置的范围,变化200%或者更多。所以建议最后返回值<1. 这里你可以通过对input 做一些函数转化,实现特殊效果,无比sin函数 cos函数 ,为什么选这些,原因简单啊 他们的值域 都在0-1 范围内啊。
(二)TypeEvaluator 估值器
上篇文章我们已经见过它了,所谓估值器就是根据当前属性百分比的变化,来计算最后属性变化后的值的,一看就明白就是把interpolator 返回的值转换成最后属性的变化值啊,就那么简单。android 系统也为网们定义3种估值器,IntEvaluator FloatEvaluator colorIntEvaluator ,也就是说系统可以对这些值进行估计,你可以回想一下 我们的属性动画是不是我们没有制定估值器,但是系统也最后实现了这个属性的动画,因为系统会跟进你选择的动画种类去选择合适的估值器,单是当我们要对别的属性做动画时候就需要自己定义插值器了,上篇文章,我们已经做过了嘛,ObjectAnimatr.ofObject()方法我们就使用过了。这里在用ValueAnimator 来实现一下。由于前面说过了直接上代码了
public class Point { float x; float y; public Point(float x, float y) { this.x = x; this.y = y; } public float getX() { return x; } public void setX(float x) { this.x = x; } public float getY() { return y; } public void setY(float y) { this.y = y; }
自定义的point 属性。
public class MyInterpolator implements android.view.animation.Interpolator { @Override public float getInterpolation(float input) { return input*input*input*input; } }
自定义的插值器,x^4 作为转换函数,
public class MytypeEvaluator implements TypeEvaluator<Point> { @Override public Point evaluate(float fraction, Point startValue, Point endValue) { float dtX = endValue.getX()-startValue.getX(); float dtY= endValue.getY() - startValue.getY(); return new Point(fraction*dtX,fraction*dtY); } }
自定义的估值器。
使用如下
mgirl = (ImageView) findViewById(R.id.iv_girl); ValueAnimator valueAnimator = ValueAnimator.ofObject(new MytypeEvaluator(), new Point(0, 0), new Point(500, 500)).setDuration(2000); valueAnimator.setInterpolator(new MyInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Point animatedValue = (Point) animation.getAnimatedValue(); mgirl.setTranslationX(animatedValue.getX()); mgirl.setTranslationY(animatedValue.getY()); } }); valueAnimator.start();
就那么简单 插值器与估值器说到这你肯定明白了。
(三) 说说对任意属性做动画。
这里从一个需求说起,我们要对一个button 的宽度做动画,使它在2000毫秒 宽度增加500px 你肯定觉简单啊 ,把botton 在x 方向放大就不ok 了,你仔细看清,我们说的是宽度增加,如果x放大化button 内部的内容也放大了,效果很难看,如果恰巧button 在布局边上,你会反省button 直接跑出布局去了,这肯定不是我们要的效果啊,马上就会想到可以用objectAnimation操作button 的宽“with”啊,ObjectAnimator.ofInt(mButton,"with",0,500)
你可以试验一下,objectAnimator是没有效果的。如果你对任意属性不加判断直接做动画的话,轻的话梅没有效果,有些属性直接回造成crash的。
结论如下:如果你做动画的属性没有set方法的话,你去做动画,之间回crash ,如果有set方法没用get方法的话 没有效果。
那怎么解决啊 官方给出了三种解决方法1 给对象加上set get方法,单是需要权限(这基本不可能实现啊) 2 用一个对象包裹 组建提供set get方法,3 使用ValueAnimator 自己操作view 的属性。
这里就说说第二种吧,各人感觉最简单的一种。代码
public class SwipButton { private Button button; public int getWith() { return button.getLayoutParams().width; } public void setWith(int with) { ViewGroup.LayoutParams layoutParams = button.getLayoutParams(); layoutParams.width = with; button.setLayoutParams(layoutParams); } }包裹过程
ObjectAnimator with = ObjectAnimator.ofInt(mgirl, "with", 0, 500); with.setDuration(2000); with.start();
使用过程ok 解决了。你可能会问为什么呢?好吧下篇文章我们继续说吧。