属性动画简单分析(一)

属性动画的核心原理也很简单: 
1)传入你要操作的对象,即目标对象,也即是Target. 
2) 传入你要操作的属性propertyName 
3) 通过反射机制,不断的调用Target对象的setPropertyName方法:当然setPropertyName方法的具体实现完全由咱们IT Monkey自己定制。

简单原理叙说完毕,那么就开始开车了: 
这里写图片描述

ObjectAnimation类本身提供了三种构造函数来进行对象的构建,默认函数为public,其余的两个是private的,默认的构造函数在这里暂且不提。如果想要创建ObjectAnimation对象的话,其内部提供了几个静态方法来创建:比如ofObject,ofInt等,鉴于本人在开发中的使用情况就从ofObject这个方法开始说起:

public static ObjectAnimator ofObject(Object target, String propertyName,
            TypeEvaluator<?> evaluator, Object... values) {
            //调用私有构造器
        ObjectAnimator anim = new ObjectAnimator(target, propertyName);
        //保存属性动画客户端传来的序列值
        anim.setObjectValues(values);
        //设置估值器
        anim.setEvaluator(evaluator);
        return anim;
    }

1)调用了私有构造器来初始化ObjectAnimator 对象,这个构造器也很简单,就是ofObject参数中传入的target和propertyName分别赋予ObjectAnimator的mTarget和mPropertyName,并将mInitialized这个表示是否初始化完成的boolean变量设置为false,该变量的作用就是用来标记动画是否可以开始! 
2)既然propertyName和target都已经复制完毕,那么很简单接下来就是处理ofObject方法传来的values了:交给setObjectValues处理

public void setObjectValues(Object... values) {
        if (mValues == null || mValues.length == 0) {

            if (mProperty != null) {
                //省略部分代码
            } else {//调用的此处
    //将values序列交给  PropertyValuesHolder的ofObject处理  
          setValues(PropertyValuesHolder.ofObject(mPropertyName,
                        (TypeEvaluator) null, values));
            }
        } else {
            super.setObjectValues(values);
        }
    }

最终会发现传入的values序列值交给了PropertyValuesHolder的静态方法ofObject,通过该方法的处理,生成了PropertyValuesHolder对象,作为参数传入了ObjectAnmiaton对象的setValues方法。为了文章的连贯性,把PropertyValuesHolder的说明暂时阁下,先简单看一个setValues方法:

//方法参数是PropertyValuesHolder,说明你可以用ObjectAnmation的setValues方法传入若干个PropertyValuesHolder对象
public void setValues(PropertyValuesHolder... values) {
        int numValues = values.length;
        mValues = values;
        //key:属性名,value:属性对应的PropertyValuesHolder
        mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
        //把传入的PropertyValuesHolder对象添加到mValuesMap中
        for (int i = 0; i < numValues; ++i) {
            PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i];
            mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
        }
        // New property/values/target should cause re-initialization prior to
        // starting
        mInitialized = false;
    }

setValues方法很简单,具体来说就是做了如下工作: 
1)将方法参数复制给ObjectAnimation对象的PropertyValuesHolder mValues[]数组; 
2)将PropertyValuesHolder对象数组添加到以propertyName为key,以PropertyValuesHolder对象为value的map中。

到此为止,从流程上来说ObjectAnimation的ofObject方法已经说名完毕,但是根据前文的说明,ofObject方法传入的values是交给了PropertyValuesHolder,我们现在看看PropertyValuesHolder这个类具体干了什么好事儿。 
PropertyValuesHolder:顾名思义,就是持有propertyName所对应的values序列值的对象,一个PropertyValuesHolder对象持有一个propertyName及其对应的values序列,只不过这个序列是通过KeyFramseSet持有,前面通过ofObject将propertyName和values对象传入进来:

public static PropertyValuesHolder ofObject(String propertyName,
            @SuppressWarnings("rawtypes") TypeEvaluator evaluator, Object... values) {
        //设置给propertyName方法 
        PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName);
        //把vlaue方法最终传给PVH
        pvh.setObjectValues(values);
        pvh.setEvaluator(evaluator);
        return pvh;
    }

values交给setObjectValues来处理:

public void setObjectValues(Object... values) {
        mValueType = values[0].getClass();
        //把values最终传给mKeyFrameSet方法
        mKeyframeSet = KeyframeSet.ofObject(values);
    }

通过代码可知最终values被传到了KeyFrameSet的ofObject里面,经过处理生成一个KeyFrameSet对象:

    public static KeyframeSet ofObject(Object... values) {
        int numKeyframes = values.length;
        //ObjectKeyframe最少两帧动画
        ObjectKeyframe keyframes[] = new ObjectKeyframe[Math.max(numKeyframes,
                2)];
        if (numKeyframes == 1) {//如果传过来的是一个值
            //动画第一帧其其实fraaction=0,该帧对应的值是0
            keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f);
            //动画第二个fraction=1,该帧对应的值就是你传入的那个值
            keyframes[1] = (ObjectKeyframe) Keyframe.ofObject(1f, values[0]);
        } else {

            keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f, values[0]);
            //把传入的其余的值根据传入的序列对i/(n-1)-->values[i]进行映射
            for (int i = 1; i < numKeyframes; ++i) {
                keyframes[i] = (ObjectKeyframe) Keyframe.ofObject((float) i
                        / (numKeyframes - 1), values[i]);
            }
        }
        //返回帧集合:传入多少个值就传多少个有多少帧
        return new KeyframeSet(keyframes);
    }

    public KeyframeSet(Keyframe... keyframes) {
        mNumKeyframes = keyframes.length;
        //帧序列集合
        mKeyframes = new ArrayList<Keyframe>();
        mKeyframes.addAll(Arrays.asList(keyframes));
        //记录第一帧
        mFirstKeyframe = mKeyframes.get(0);
        //记录最后一帧
        mLastKeyframe = mKeyframes.get(mNumKeyframes - 1);
        mInterpolator = mLastKeyframe.getInterpolator();
    }

上面的算法很简单,跟《线性贝塞尔曲线简单说明》这篇博文算法思路完全一样!!!在这里稍微总结一下: 
1)客户端通过ObjectAnimation的ofObject()方法传入多少个value(一个除外)就有多少个KeyFrame对象,每个KeyFrame对象持有与KeyFrame对象创建顺序对应的value 
2)KeyFrame有一个mFraction变量,该变量的初始化计算算法为: 
mFraction = (float)i/(values.length-1) 
简单的用图表来表示values和KeyFrame之间的关系就是: 
这里写图片描述

到此为止,算是完成了对ObjectAnimation对象的初始化工作,再次简单梳理下,分成大致几个点: 
1)通过ObjectAnimation的ofXXX方法,设置propertyName和values。 
2)将propertyName和values封装成PropertyValueHolder对象:每个PropertyValueHolder对象持有values组成的帧序列对象KeyFrameSet对象; 
3)将步骤2创建的PropertyValueHolder对象用ObjectAnimation的mValues 数组保存起来;然后将propertyName作为key,PropertyValueHolder作为value保存到mValuesMap中。

最终简单的创建骨架可以用如下图来作为总结: 
这里写图片描述

总体上,ObjectAnimation的创建流程简单分析完毕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值