Property动画二(ValueAnimator,OjbectAnimator,PropertyValuesHolder,KeyFrame)

ValueAnimator

属性动画的核心类ValueAnimator,这个类按照字面意思理解,就是给值动画,意思就是给值做动画。这个类有两个直接子类,OjbectAnimator,TimeAnimator。下面我们看看ValueAnimator类常用的api。
创建ValueAnimator对象又几种方式,下面是通过构造函数直接创建。

ValueAnimator animator = new ValueAnimator();
//setIntValues()方法传入一个参数,则这个数就是最终值,传入两个,则第一个参数是初始值,第二个是最终值
//传入三个或三个以上的参数,则第一个是最初值,最后一个是最终值,中间的是过渡值
animator.setInValues(10);

//传入一个参数,则这个数就是最终值,传入两个,则第一个参数是初始值,第二个是最终值
//传入三个或三个以上的参数,则第一个是最初值,最后一个是最终值,中间的是过渡值
ValueAnimator valueAnimator4 = ValueAnimator.ofInt(10);
ValueAnimator valueAnimator1 = ValueAnimator.ofInt(10, 100);//可以出入多个参数
ValueAnimator valueAnimator2 = ofFloat(1.0f, 2.0f);//可以出入多个参数
ValueAnimator valueAnimator3 = ValueAnimator.ofObject(new IntEvaluator(), 1, 10);//可以出入多个参数

下面通过一个示例演示,来讲解其他api

//创建ValuAnimator对象
ValueAnimator valueAnimator = new ValueAnimator();
//设置动画时间
valueAnimator.setDuration(5000);
final float startX = iv.getLeft() + iv.getWidth()/2f;
final float startY = iv.getTop() + iv.getHeight()/2f;
//设置值
valueAnimator.setObjectValues(new PointF(startX,startY));
//设置重复次数,ValueAnimator.INFINITE 这个常量表示无限循环,
// ValueAnimator.RESTART 这个常量表示完成一次后,在继续从头开始
// ValueAnimator.REVERSE 这个常量表示完成一次动画后,重复时,从结尾倒退到从头
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
//表示动画延时多少毫秒后执行
valueAnimator.setStartDelay(200);
//设置插值器
valueAnimator.setInterpolator(new LinearInterpolator());
//设置自定义的估值器
valueAnimator.setEvaluator(new TypeEvaluator() {
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        //如果valueAnimator.setObjectValues(new PointF(startX,startY),new PointF(0,0));
        //传入了两个值,则第一个值就是startValue,第二个值就是endValue
        //如果valueAnimator.setObjectValues(new PointF(startX,startY));值传入了一
        //个值,则startValue为null,endValue的值就是这个传入的值
        //如果valueAnimator.setObjectValues(new PointF(startX,startY),new PointF(0,0),...);
        // 传入3个以及3个以上的参数,则数据的过度顺序是,从第一个参数值变化到第二个参数值,
        //再从第二个参数值,变化到第三个参数值,以此类推
        //LogUtil.i("startValue===="+startValue+"---endValue="+endValue);
        PointF p = new PointF();
        //从view自身的中心点做起始点
        p.x = fraction * 1 * 200 + startX;
        // p.y = (fraction * 1)* (fraction * 1) * 100f + startY;
                //从坐标(0,0)作为起始点
                p.x = fraction * 3 * 200 ;
                p.y = (fraction * 3)* (fraction * 3) * 100f ;
                return p;
            }
        });
        valueAnimator.start();
	//设置动画的状态监听,里面的方法可以按需覆盖,这里为了演示,全部覆盖了
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationCancel(Animator animation) {
                super.onAnimationCancel(animation);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                LogUtil.i("animation is end");
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                super.onAnimationRepeat(animation);
            }

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
            }

            @Override
            public void onAnimationPause(Animator animation) {
                super.onAnimationPause(animation);
            }

            @Override
            public void onAnimationResume(Animator animation) {
                super.onAnimationResume(animation);
            }
});
//设置属性更新监听
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator animation) {
          PointF p = (PointF) animation.getAnimatedValue();
          iv.setX(p.x);
          iv.setY(p.y);
      }
});

除了上面的set方法,还有想对应的get方法,读者可以自己看api文档查看用法


ObjectAnimator

下面讲下ValueAnimator的子类ObjectAnimator的使用,由于ObjectAnimator类是继承ValueAnimator,
所以上面演示的ValueAnimator的方法,ObjectAnimator都能够使用。
下面演示一个通过PropertyValuesHolder来创建ObjectAnimator

PropertyValuesHolder pvh_alpha = PropertyValuesHolder.ofFloat("alpha",1f,0.5f);
PropertyValuesHolder pvh_scaleX = PropertyValuesHolder.ofFloat("scaleX",1f,0.5f);
PropertyValuesHolder pvh_scaleY = PropertyValuesHolder.ofFloat("scaleY",1f,0.5f);
ObjectAnimator.ofPropertyValuesHolder(iv,pvh_alpha,pvh_scaleX,pvh_scaleY).setDuration(5000).start();

从PropertyValuesHolder这个类的字面意思就可以知道,这个类适用于属性、值保存的。
可以通过这个类,将属性和值,先保存起来,后面在一起通过ofPropertyValuesHolder方法设置给ObjectAnimator。
下面给出一个ObjectAnimator常用的示例:

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv,"alpha",1f,0f,1f);
objectAnimator.setDuration(1000);
objectAnimator.start();

这种用法有一点需要注意,就是传入的属性字符串,必须是作用的对象有这个属性,并且至少提供该属性的setXxx方法。如果没有提供初始值,则需要提供getXxx方法。

属性动画的原理:就是通过反射调动对象的setXxx和getXxx方法不断的改变对象的属性,来达到动画的效果。通过PropertyValuesHolder类的calculateValue方法计算属性值,通过PropertyValuesHolder类的setupValue方法来通过反射来调用对象的setXxx和getXxx方法来设置改变属性值和获取属性值。


ViewPropertyAnimator

View类的animate()方法,是在Android 3.1系统上新增的一个方法,其作用就是返回ViewPropertyAnimator的实例对象。
通过ViewPropertyAnimator对象,可以操作很多常用的动画效果。下面我们看一个简单的示例

iv.animate().alpha(0.5f).scaleY(2f) .scaleX(2f).translationX(50f).rotation(180).setDuration(5000);

通过一行链式调用的代码,就完成了一个复杂的动画效果。其中iv.animator()返回的就是
一个ViewPropertyAnimator对象。具体各个方法的介绍api

ViewProoertyAnimator还提供了By结尾的方法,
有By结尾和没By结尾的区别:
每个动画都有一个By的后缀的方法。加上By的意思是,继续动画这么多数值。不加By的意思是动画到这个数值。

有By:变化偏移

无By:变化到

优点:
1.使用方便简洁。这个类是专门对View做动画设计的,并且提供了常用的动画的一些api。
如果只是对view进行动画,并且作用到view上的属性表示很特殊的属性,使用这个类做属性动画是非常方便的。
2.性能更优,多个属性同时做动画时,只调用一次invalidate方法进行刷新ui(而n个ObjectAnimator就会调用用n次invalidate方法)。

缺点:
1.不够灵活,这能作用到view上
2.View未提供的属性,就无法使用使用。

易用性方面:
ViewPropertyAnimator > ObjectAnimaor > ValueAnimator

灵活性方面:
ValueAnimator > ObjectAnimator > ViewPropertyAnimator


PropertyValuesHolder

PropertyValuesHolder:上面已经提了一下,这个类就是用于保存属性和属性值。通过查看其PropertyValuesHolder api ,可以发现提供了如下的一些静态方法构建其对象。

static PropertyValuesHolder	ofFloat(String propertyName, float... values)

static PropertyValuesHolder	ofFloat(Property<?, Float> property, float... values)

static PropertyValuesHolder	ofInt(Property<?, Integer> property, int... values)

static PropertyValuesHolder	ofInt(String propertyName, int... values)

static PropertyValuesHolder	ofKeyframe(Property property, Keyframe... values)

static PropertyValuesHolder	ofKeyframe(String propertyName, Keyframe... values)

static <V> PropertyValuesHolder	ofObject(Property property, TypeEvaluator<V> evaluator, V... values)

static PropertyValuesHolder	ofObject(String propertyName, TypeEvaluator evaluator, Object... values)

下面我们就以ofFloat(String propertyName, float… values)这个方法来做示例:

//第一个参数是属性名称,后面是可变参数,是属性值
PropertyValuesHolder holder_alpha = PropertyValuesHolder.ofFloat("alpha",1f,0.5f);
PropertyValuesHolder holder_scaleX = PropertyValuesHolder.ofFloat("scaleX",1f,0.5f);


这样就创建了一个PropertyValuesHolder 对象,下面我们就看看如何使用它
//通过ObjectAnimator的ofPropertyValuesHolder方法来创建ObjectAnimator对象。
ObjectAnimator.ofPropertyValuesHolder(iv,holder_alpha,holder_scaleX).setDuration(5000).start();

在看看ObjectAnimator的如下使用方式:

ObjectAnimator.ofFloat(iv,"alpha",0.5f).start();

其实这种方式,内部,还是将传入属性名名和属性值,用PropertyValuesHolder进行了封装。最终计算属性值和调用对象的setXxx方法和getXxx方法也是通过PropertyValuesHolder来完成的。

讲解完PropertyValuesHolder的ofFloat方法后,其他类似的方法的使用也是相同的。下面来看看ofObject方法,这个方法和上面介绍的ofFloat方法有些不同,这个方法中,要传入估值器,为什么这个方法要传入插值器,其他方法就不需要传入插值器,这是因为ofFloat,ofInt这些方法创建的PropertyValuesHolder对象,被ObjectAnimator拿来构建具体的ObjectAnimator对象时,它就能够从属性值来判断这些属性值都是float类型的,这时,构建的ObjectAnimator时就会使用系统默认提供的FloatEvaluator,而我们这里使用的是ofObject方式构建的PropertyValuesHolder,通过PropertyValuesHodler构建的ObjectAnimator时,就不知道具体的属性类型,也就无法使用何种方式估值。所以需要传入估值器。这个方法的具体示例就不演示了,使用和ofFloat方法差不多。


KeyFrame

KeyFrame;关键帧。通过查看KeyFrame api文档中对这个类的描述是,这个类为动画保存了时间和值的键值对。下面来看看构建KeyFrame的一些方法:

static Keyframe	ofFloat(float fraction, float value)

static Keyframe	ofFloat(float fraction)

static Keyframe	ofInt(float fraction)

static Keyframe	ofInt(float fraction, int value)

static Keyframe	ofObject(float fraction)

static Keyframe	ofObject(float fraction, Object value)

这些方法使用都类似,我们就以static Keyframe ofFloat(float fraction, float value)方法举例,演示其使用:

//第一个参数是属性的比例,第二个参数是属性值
Keyframe keyframe = Keyframe.ofFloat(0,0);//属性比例是0时,对应的属性值是0
Keyframe keyframe1 = Keyframe.ofFloat(0.5f,100);//属性比例是0.5时,对应的属性值是100
Keyframe keyframe2 = Keyframe.ofFloat(1,80);//属性比例是1时,对应的属性值是80
PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofKeyframe("progress", keyframe, keyframe1, keyframe2);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(customProgressView, propertyValuesHolder);
objectAnimator.setDuration(3000);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();

注意:使用Keyframe来构建动画,至少要有两个或两个以上帧.。否则会报错。KeyFrmae的其他方法和ofFloat类似,就不一 一举例演示了,大家可以参考api文档去使用。

动画使用的注意事项:

1.内存泄漏,无限循环的动画,要做activity销毁时,取消动画。
2.要注意兼容性的问题
3.使用帧动画时,需要注意防止oom

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值