通过源码,手把手带你学属性动画(三) - ValueAnimator进阶

转载请注明出处:http://blog.csdn.net/my_truelove/article/details/52612963

访问 ruicb.com,一键抵达我的博客!


主要内容:上篇侧重介绍了ofFloat()方法,以及与动画相关的方法、监听,本节将继续介绍剩下的 ofObject() 和 ofPropertyValuesHolder() 方法,以及相关的 TypeEvaluator 和 PropertyValuesHolder。

如果还没有看上篇《通过源码,手把手带你学属性动画(二) - ValueAnimator基础》的,建议先看完再继续往下看。

下面直接开始讲解。

1. ofObject() 与 TypeEvaluator

在介绍ofObject()之前,先来说说TypeEvaluator,可以理解为类型计算器,一般动画效果不会用到,但是有必要了解一下,一来以备不时之需,二来有利于我们后面读懂源码。

1.1 类型计算器-TypeEvaluator

该类是一个接口,我们看看 TypeEvaluator 接口文档 的介绍:

Evaluators allow developers to create animations on arbitrary property types, by allowing them to supply custom evaluators for types that are not automatically understood and used by the animation system.

大概意思是:对不能被动画系统自动识别且使用的类型提供自定义估值器,以允许开发者对任意类型的属性值实施动画

概括来说:告诉属性动画系统如何从开始值过渡到结束值!给其一个动画进度,返回一个当前进度下对应的属性值,可以是一个数值,也可以是一个点,或者更复杂的数据类型。

TypeEvaluator 只有一个接口方法,我们在自定义类型计算时需要覆写该方法:

T evaluate(float fraction, T startValue, T endValue)

该方法的返回值、开始值、结束值均使用泛型声明,说明该接口不关心具体的值类型,我们只需要根据当前动画进度fraction,来计算改变后的属性值并返回即可。

其一般计算过程可简化为:返回值 = 开始值 + (终点值-开始值) * 进度

系统内置了7种类型计算器:

7种计算器

系统的类型计算器,都根据实际数据类型覆写了evaluate()方法,包括整形(IntEvaluator)、浮点型(FloatEvaluator)、颜色(ArgbEvaluator)、点(PointFEvaluator)等类型,已基本满足实际开发的大部分需求,只是在特殊需求下我们可能需要自定义。

强烈建议大家去看看各个类的 evaluate() 方法实现,就不再一一介绍了,一看就懂。

下面我们介绍 ofObject() 的使用,同时会讲解如何如何自定义 TypeEvaluator。

1.2 ofObject()使用

在上篇介绍 ofFloat() 时,因为我们明显是对 float 数据类型做动画,所以系统默认帮我们指定了 FloatEvaluator,在后面的源码分析中会带大家看的。ofArgb() 与 ofInt() 同理。

现在我们想对点(Point)类型做动画,然而我们没有发现 ofPoint() 之类的方法,这就尴尬了!别急,系统为我们提供了 ofObject() 方法,以支持任意类型的数据,这个好!但是,随之而来有个问题:

既然是任意数据类型,那么系统肯定不知道你传的是啥,也就是上面说的“无法自动识别”,那么怎么给你做动画?

比如根据时间,系统知道动画进行到一半了,你用 ofFloat(0f, 100f),系统按动画进度能算出来是 50,但是你对点(Point)做动画,从p1(0,0)到p2(100,100),用 ofObject(p1,p2),系统咋给你算?

所以,使用 ofObject()就需要搭配上面讲的 TypeEvaluator,别忘了他的职责:告诉属性动画系统如何从开始值过渡到结束值

这里写图片描述

上代码!下面,我们演示如何从一个点动画过渡到另一个点,此处用PointF类型表示点,表示坐标值是float类型的。

我们自然而然会想到使用系统内置的 PointFEvaluator,但由于其需要在LOLLIPOP版本(即Android 5.0)以上才可以使用,所以为了兼容,我们仿照PointFEvaluator自定义一个MyPointFEvaluator,如下:

public class MyPointFEvaluator implements TypeEvaluator<PointF> {
    PointF pointF;
    @Override
    public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
        float x = startValue.x + (endValue.x - startValue.x) * fraction;
        float y = startValue.y + (endValue.y - startValue.y) * fraction;

        // 该方法在动画过程中的每一帧都会调用,
        // 使用此举以避免重复创建PointF对象
        if (null == pointF){
            pointF = new PointF();
        }
        pointF.set(x,y);
        return pointF;
    }
}

evaluate(fraction,startValue,endValue)方法的三个参数是系统所知道,系统不知道的是如何根据进度,以及开始和结束的值,计算当前值!

那我们就需要自己实现evaluate()方法体,告诉系统要怎么算,并最后返回!代码如上所示,感受一下吧!

接下来,使用ofObject实现从点startPoint(0f, 0f)动画过渡到endPoint(5f, 5f),代码如下:

public static void anim1(){
    //定义动画的值范围
    PointF startPoint = new PointF(0f, 0f);
    PointF endPoint = new PointF(5f, 5f);
    ValueAnimator valueAnimator =
            ValueAnimator.ofObject(new MyPointFEvaluator(), startPoint, endPoint);
    //设置动画时长
    valueAnimator.setDuration(100);
    //添加对值的监听,获取值
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            PointF pointF = (PointF) animation.getAnimatedValue();
            Log.d("ruicbAndroid", "onAnimationUpdate:"+ pointF.toString());
        }
    });
    //启动动画
    valueAnimator.start();
}

以上代码我们已经比较熟悉了,与ofFloat()的用法类似,不再介绍。具体的打印结果不再粘贴。

2. ofPropertyValuesHolder() 与 PropertyValuesHolder

同样,我们先看看 PropertyValuesHolder。

2.1 PropertyValuesHolder

在属性动画的源码实现中,PropertyValuesHolder 起到了关键作用,其负责持有对象的属性和值。有关该类的作用,官方文档 注释如下:

PropertyValuesHolder objects can be used to create animations with ValueAnimator or ObjectAnimator that operate on several different properties in parallel.

意思是:PropertyValuesHolder 可以被 ValueAnimator 或 ObjectAnimator用来创建动画,以同时操作多个不同属性。

我们可以使用 ofPropertyValuesHolder(PropertyValuesHolder… holders)方法,来实现对多个属性值同时进行动画。具体的使用,将在介绍 ObjectAnimator 时介绍,此处暂不例举。

下面先看看如何在 ofPropertyValuesHolder() 方法中使用 PropertyValuesHolder。

2.2 ofPropertyValuesHolder()

该方法主要作用就是:支持我们同时对多个属性进行动画

其使用与其他方法无异,不再详细介绍,只给出创建动画的关键代码,感兴趣的自行打印结果看看。我将在介绍ObjectAnimator时再演示该方法的作用,在此仅给出简单的示例,你只需要知道有这个方法就好了。

PropertyValuesHolder holder = PropertyValuesHolder.ofFloat("", 0f, 5f);
ValueAnimator valueAnimator =
        ValueAnimator.ofPropertyValuesHolder(holder);

PropertyValuesHolder.ofFloat(“”, 0f, 5f),第一个参数表示属性,在此传空,在介绍ObjectAnimator再介绍该参数。

3.总结

本文主要是对上文的一个补充介绍,如果你认真看完,肯定会有收获!至此,有关构造 ValueAnimator 对象的工厂方法已经介绍完毕,并介绍了一些与动画相关的方法。

要知道,在实际开发中,我们使用 ObjectAnimator 更多一些,我为什么还会在 ValueAnimator 上讲这么多呢?原因有二:

  • ObjectAnimator 继承自 ValueAnimator,ObjectAnimator
    实现动画的核心仍然是借助ValueAnimator,所以理解ValueAnimator将更加有利于掌握ObjectAnimator;
  • 在此处介绍了一些通用API,等后期介绍ObjectAnimator 时,我们就可以专心实现一些动画效果,而不用再纠结于介绍API了;

下篇我们一起来学习一下动画中的插值器!

下篇已更新:《通过源码,手把手带你学属性动画(四) - 理解插值器(附神器)


扫描下方二维码,关注我的公众号,及时获取最新文章推送!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值