在android 3.0的时候,谷歌提供的Property Animation这个概念,与之前的tween动画相比,还是有明显的区别。举个最简单的例子,我们在一个imageview上面增加一个onclick事件,随后我们来一个位移动画,这时候我们再点击这个imageview,就会发现点击事件没了,然后我们又会很离奇的发现在一开始加载Imageview的那个地方,却可以响应这个点击事件,这不是很操蛋吗。。。从原理上来说,tween动画,仅仅是改变了view的绘图位置以及相关属性,没有牵扯到view本身这个对象的操作,所以才会带来如此大的麻烦。基于这一点,属性动画这个概念就很有必要去掌握。
把相关类拿出来说说 ObjectAnimator ValueAnimator PropertyValuesHolder AnimatorSet TypeEvaluator AnimatorInflater,其实对于效果展示上,两者肯定没有什么区别的,无非就是设置动画效果,动画时间,动画差值器,动画监听这几类,如果需要详细了解,请参考http://developer.android.com/guide/topics/resources/animation-resource.html#Property
下面我们来看看具体使用方法
(1)1句话演示基本用法
ObjectAnimator.ofFloat(click, "alpha", 1F, 0F).setDuration(1000).start();
简单吧,就一句话定义了alpha的操作
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
看api,click就是执行动画的对象,propertyName就是动画属性,这里还可以选择诸如scaleX之类的多种对象,values就是动画参数值,比如我们这边如果写1F, 0F, 1F, 0F,他就会在1000毫秒内执行2次渐变效果。有个地方要注意下,就是propertyName,这个不是随便乱写的,具体有哪些我暂时也没找到完整的说明,待我后续补充
(2)联合多动画实现
跟tween一样,这边提供了animatorSet这个对象
ObjectAnimator ani1=ObjectAnimator.ofFloat(click, "alpha", 1F, 0F);
ObjectAnimator ani2=ObjectAnimator.ofFloat(click, "translationX", 100, 300);
ObjectAnimator ani3=ObjectAnimator.ofFloat(click, "translationY", 100, 300);
这边写了3个动画效果
然后来一个animatorSet
AnimatorSet set=new AnimatorSet();
我们可以这样玩:一起执行
set.playTogether(ani1, ani2, ani3);
还可以这样玩:顺序执行
set.playSequentially(ani1, ani2, ani3);
还能自己安排先后顺序玩
set.play(ani1).after(ani2);
set.play(ani3).before(ani2);
是不是很牛逼
最后播放一下
set.setDuration(2000);
set.start();
注意一点就是这边是animatorSet不是animationSet
(3)写了那么多效果,我们不能忘记监听一下动画的开始与结束,也非常简单,走你
ani1.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
同样提供了动画开始、结束、取消、重复这些动作的监听。
我们这样看有时候也会觉得麻烦,比如我们只要监听动画结束,写那么多不是太乱了,OK,这边提供了AnimatorListenerAdapter,让你轻松控制自己想控制的
ani1.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
});
这样就可以了
(4)使用不存在的动画效果名称,去自定义视图动画
刚才我们说到了,那个propertyName如果随便乱写,是会有问题的,那我现在就是打算乱写,可不可以玩?答案是肯定的。我们来段代码
ObjectAnimator ani1=ObjectAnimator.ofFloat(click, "yd", 100, 200).setDuration(1000);
ani1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float tranX= (float) animation.getAnimatedValue("yd");
click.setTranslationX(tranX);
}
});
ani1.start();
这边有一个自定义的动画效果“移动”,我们利用他在1000毫秒内执行100-200的这个操作,通过getAnimatedValue("yd")来获取到这个动画效果偏移值,然后再设置setTranslationX来自定义X轴的移动动画
(5)使用propertyValuesHolder去执行联合动画
之前说到用animatorSet去执行多动画效果,这边还提供了PropertyValuesHolder把多种动画同时加到一个对象上进行多动画操作,还是看代码
PropertyValuesHolder holder1=PropertyValuesHolder.ofFloat("alpha", 1F, 0F);
PropertyValuesHolder holder2=PropertyValuesHolder.ofFloat("translationX", 100, 200);
PropertyValuesHolder holder3=PropertyValuesHolder.ofFloat("translationY", 100, 200);
ObjectAnimator.ofPropertyValuesHolder(click, holder1, holder2, holder3).setDuration(1000).start();
(6)使用ValueAnimator去执行动画操作
除了ObjectAnimator,ValueAnimator同样也可以执行各种操作,只不过他也要自己来实现真实的动画过程,这点跟之前自定义动画属性差不多,看代码
ValueAnimator animator=ValueAnimator.ofFloat(0, 100);
animator.setTarget(click);
animator.setDuration(1000);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void onAnimationUpdate(ValueAnimator animation) {
<span style="white-space:pre"> </span>click.setTranslationY((float) animation.getAnimatedValue());
}
});
是不是跟那个几乎一模一样的写法,区别在于ValueAnimator实例化对象的时候不是把对象视图直接添加进来进行构造而已
(7)TypeEvaluator的使用
直接通过ValueAnimator构造方法去创建实例,无法使用ofFloat或者ofInt,可以通过TypeEvaluator传入不同的泛型对象来返回相应需要的值,以便于我们在onAnimationUpdate中更加方便的使用。看代码找区别
ValueAnimator animator=new ValueAnimator();
animator.setDuration(2000);
animator.setObjectValues(new PointF(0, 0));
animator.setInterpolator(new LinearInterpolator());
animator.setEvaluator(new TypeEvaluator<PointF>() {
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
PointF pointF=new PointF();
//随便写的自定义位置
pointF.x=100*fraction*3;
pointF.y=0.5f*100*fraction*3*fraction*3;
return pointF;
}
});
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF pointF= (PointF) animation.getAnimatedValue();
click.setTranslationX(pointF.x);
click.setTranslationY(pointF.y);
}
});
这边我们选择返回了RectF这种类型对象,便于我们存储根据估值器fragction而获得的值。fraction是一个从0到1的时间因子,某种意义上也是这个动画的执行进度,也同样可以反映差值器的走势。evaluate里面返回的值,就是后面onAnimationUpdate里面的入参。
(8)使用xml文件来创建属性动画
同tween一样,可以再xml中定义好animator动画。这边有一个地方不同,就是之前我们建立的都是/anim,这边却是建立/animator
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:propertyName="scaleX"
android:valueFrom="1.0"
android:valueTo="2.0"
android:valueType="floatType">
</objectAnimator>
翻译一下,就是
ObjectAnimator.ofFloat(click, "<span style="font-family: Arial, Helvetica, sans-serif;">scaleX</span><span style="font-family: Arial, Helvetica, sans-serif;">", 1F, 2F).setDuration(1000).start();</span>
在java中,我们使用AnimatorInflater去加载
Animator animator=AnimatorInflater.loadAnimator(MainActivity.this, R.animator.scalex);
animator.setTarget(click);
animator.start();
(9)使用xml文件来创建属性动画
这次我们使用set来创建xml动画
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together" >
<objectAnimator
android:duration="1000"
android:propertyName="scaleX"
android:valueFrom="1"
android:valueTo="0.5" >
</objectAnimator>
<objectAnimator
android:duration="1000"
android:propertyName="scaleY"
android:valueFrom="1"
android:valueTo="0.5" >
</objectAnimator>
</set>
注意看这边有个ordering,这个就是来描述动画们是顺序执行还是同时执行的描述
如果想在android3.0一下使用属性动画,那么请使用NineOldAndroids
基本上就这么多,要有什么意见,请各位看官指点一二