原文地址:点击打开链接
1.ValueAnimator
ValueAnimator可以说是整个属性动画框架的核心类,动画的驱动就是在此类中实现的。下面举一个ValueAnimator的实例:
- ValueAnimator anim= ValueAnimator.ofInt(0, 40);
- animation.setDuration(40);
- animation.start();
然后通过ValueAnimator的AnimatorUpdateListener可以得到动画执行每一帧所返回的值,
- anim.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- //frameValue是通过startValue和endValue以及Fraction计算出来的
- int frameValue = (Integer)animation.getAnimatedValue();
- //利用每一帧返回的值,可以做一些改变View大小,坐标,透明度等等操作
- }
- });
究竟ValueAnimator是怎么工作的呢,让我根据以上代码一句一句的进行分析,首先来看ValueAnimator.ofInt(0, 40);
- //ofInt或ofFloat提供的values最终都被包装成一个PropertyValuesHolder
- //不同于ObjectAnimator这里提供的值必须两个以上,ObjectAnimator可以只提供一个endValue
- public static ValueAnimator ofInt(int... values) {
- ValueAnimator anim = new ValueAnimator();
- anim.setIntValues(values);
- return anim;
- }
- /**
- * 通过以下代码可以看出,PropertyValuesHolder以某种方式保存了values的值。
- * 在ValueAnimator中操作的都是valuesHolder对象
- * @param values
- */
- public void setIntValues(int... values) {
- if (values == null || values.length == 0) {
- return;
- }
- if (mValues == null || mValues.length == 0) {
- //这里PropertyValuesHolder.ofInt提供的字符串参数为“”,是因为ValueAnimator并不提供目标对象,自然无法提供属性名称
- setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofInt("", values)});
- } else { //这里是为了处理重复设置
- PropertyValuesHolder valuesHolder = mValues[0];
- valuesHolder.setIntValues(values);
- }
- // New property/values/target should cause re-initialization prior to starting
- mInitialized = false;
- }
- //把PropertyValuesHolder对象保存起来
- public void setValues(PropertyValuesHolder... values) {
- int numValues = values.length;
- mValues = values;
- mInitialized = false;
- }
下面再来看一下PropertyValuesHolder中是以什么方式来保存提供的values值的
- /**
- * IntPropertyValuesHolder继承自PropertyValuesHolder ,用来封装int类型的值
- **/
- public static PropertyValuesHolder ofInt(String propertyName, int... values) {
- return new IntPropertyValuesHolder(propertyName, values);
- }
来看IntPropertyValuesHolder类
- public IntPropertyValuesHolder(String propertyName, int... values) {
- super(propertyName);
- setIntValues(values);
- }
- /**
- * 这里会发现调用了父类的setIntValues方法,
- * 并且产生了一个mKeyframeSet对象
- * @param values
- */
- @Override
- public void setIntValues(int... values) {
- super.setIntValues(values);
- mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet;
- }
再回到PropertyValueHolder查看实现
- /**
- * mValueType作用是确定ObjectAnimator执行set方法时
- * 的参数类型
- * 而values被包装成了一个KeyframeSet
- * @param values
- */
- public void setIntValues(int... values) {
- mValueType = int.class;
- mKeyframeSet = KeyframeSet.ofInt(values);
- }
再进入KeyframeSet查看KeyframeSet.ofInt(values)具体实现
- /**
- * 从此方法可以看到,values数组中的每一个值都被包装成了IntKeyframe,
- * IntKeyframe保存一个当前值的fraction,value和mValueType。
- * IntKeyframeSet则保存是一组IntKeyframe的集合。
- * @param values
- * @return
- */
- public static KeyframeSet ofInt(int... values) {
- int numKeyframes = values.length;
- IntKeyframe keyframes[] = new IntKeyframe[Math.max(numKeyframes,2)];
- if (numKeyframes == 1) { //这里只可能是ObjectAnimator才会发生,
- keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f); //这里value为0,默认从ObjectAnimator中的目标对象中得到
- keyframes[1] = (IntKeyframe) Keyframe.ofInt(1f, values[0]);
- } else {
- keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f, values[0]);
- for (int i = 1; i < numKeyframes; ++i) { //根据值个数拆分
- keyframes[i] = (IntKeyframe) Keyframe.ofInt((float) i / (numKeyframes - 1), values[i]);
- }
- }
- return new IntKeyframeSet(keyframes);
- }
从这里可以看到,当初始化ValueAnimator时,同时也把传入的每一个数据值包装成了一个Keyframe,
并保存在KeyframeSet中,而KeyframeSet则是在PropertyValueHolder初始化的。
初始化工作完成了,然后通过animation.setDuration(40);设置duration的值,这个非常重要。
然后通过anim.start(),开始执行动画
- /**
- *所有执行了Start方法的ValueAnimator都会被临时保存在sAnimations
- */
- private static final ThreadLocal<ArrayList<ValueAnimator>> sPendingAnimations =
- new ThreadLocal<ArrayList<ValueAnimator>>() {
- @Override
- protected ArrayList<ValueAnimator> initialValue() {
- return new ArrayList<ValueAnimator>();
- }
- };
- /**
- *
- * @param playBackwards Whether the ValueAnimator should start playing in reverse.
- *
- */
- private void start(boolean playBackwards) {
- /**
- * 确保start方法是在UI线程中执行,因为UI线程在ActivityThread中
- * 会初始化一个Looper
- */
- if (Looper.myLooper() == null) {
- throw new AndroidRuntimeException("Animators may only be run on Looper threads");
- }
- mPlayingBackwards = playBackwards;
- mCurrentIteration = 0;
- mPlayingState = STOPPED; //动画初始执行状态
- mStarted = true;
- mStartedDelay = false;
- sPendingAnimations.get().add(this); //所有执行start方法的ValueAnimator都会被临时保存到此集合
- if (mStartDelay == 0) {
- // This sets the initial value of the animation, prior to actually starting it running
- setCurrentPlayTime(getCurrentPlayTime());
- mPlayingState = STOPPED;
- mRunning = true;
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- //告诉注册的了这个动画的所有监听,动画已经开始运行
- tmpListeners.get(i).onAnimationStart(this);
- }
- }
- }
- AnimationHandler animationHandler = sAnimationHandler.get();
- if (animationHandler == null) {
- //初始化唯一一个animationHandler
- animationHandler = new AnimationHandler();
- sAnimationHandler.set(animationHandler);
- }
- animationHandler.sendEmptyMessage(ANIMATION_START);
- }
- @Override
- public void start() {
- start(false);
- }
属性动画逐帧更新都是由handler不断发生消息来实现的,下面就来看一下 AnimationHandler的实现
- /**
- * 马上就开始执行的动画集合
- */
- private static final ThreadLocal<ArrayList<ValueAnimator>> sAnimations =
- new ThreadLocal<ArrayList<ValueAnimator>>() {
- @Override
- protected ArrayList<ValueAnimator> initialValue() {
- return new ArrayList<ValueAnimator>();
- }
- };
- /**
- * 需要延时执行的所有动画都会被临时保存到sDelayedAnims
- */
- private static final ThreadLocal<ArrayList<ValueAnimator>> sDelayedAnims =
- new ThreadLocal<ArrayList<ValueAnimator>>() {
- @Override
- protected ArrayList<ValueAnimator> initialValue() {
- return new ArrayList<ValueAnimator>();
- }
- };
- /**
- * 执行结束的所有动画都会被临时保存到sEndingAnims
- */
- private static final ThreadLocal<ArrayList<ValueAnimator>> sEndingAnims =
- new ThreadLocal<ArrayList<ValueAnimator>>() {
- @Override
- protected ArrayList<ValueAnimator> initialValue() {
- return new ArrayList<ValueAnimator>();
- }
- };
- /**
- *
- * 用来驱动动画执行的handler,
- * 所有的属性动画都会用同一个handler来处理。
- * 此handler主要处理动画开始动作,以及动画的每一帧
- */
- private static class AnimationHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- boolean callAgain = true;
- //已经准备开始执行的动画
- ArrayList<ValueAnimator> animations = sAnimations.get();
- //需要延迟执行的动画
- ArrayList<ValueAnimator> delayedAnims = sDelayedAnims.get();
- switch (msg.what) {
- //start方法执行后,会发送消息执行ANIMATION_START中的代码
- case ANIMATION_START:
- ArrayList<ValueAnimator> pendingAnimations = sPendingAnimations.get();
- if (animations.size() > 0 || delayedAnims.size() > 0) {
- callAgain = false;
- }
- /**
- * 由于一个动画的开始可能触发另外一个动画,意味着可能有新的动画被添加进pendingAnimations,
- * 所以这里不断遍历直到pendingAnimations为空
- */
- while (pendingAnimations.size() > 0) {
- ArrayList<ValueAnimator> pendingCopy =
- (ArrayList<ValueAnimator>) pendingAnimations.clone();
- pendingAnimations.clear();
- int count = pendingCopy.size();
- for (int i = 0; i < count; ++i) {
- ValueAnimator anim = pendingCopy.get(i);
- //如果动画没有延迟时间,则把动画添加进入sAnimations,意味着动画即将执行
- if (anim.mStartDelay == 0) {
- anim.startAnimation();
- } else { //如果动画有一个延迟执行时间,则把动画添加进延迟集合delayedAnims
- delayedAnims.add(anim);
- }
- }
- }
- // 注意,这里没有break,那么ANIMATION_FRAME中代码将继续执行
- case ANIMATION_FRAME:
- //获取当前时间,通过减去startTime,计算差值
- long currentTime = AnimationUtils.currentAnimationTimeMillis();
- ArrayList<ValueAnimator> readyAnims = sReadyAnims.get();
- ArrayList<ValueAnimator> endingAnims = sEndingAnims.get();
- //这里检查delayedAnims中动画是否可以被执行,我们可以不管这部分
- int numDelayedAnims = delayedAnims.size();
- for (int i = 0; i < numDelayedAnims; ++i) {
- ValueAnimator anim = delayedAnims.get(i);
- if (anim.delayedAnimationFrame(currentTime)) {
- readyAnims.add(anim);
- }
- }
- int numReadyAnims = readyAnims.size();
- if (numReadyAnims > 0) {
- for (int i = 0; i < numReadyAnims; ++i) {
- ValueAnimator anim = readyAnims.get(i);
- anim.startAnimation();
- anim.mRunning = true;
- delayedAnims.remove(anim);
- }
- readyAnims.clear();
- }
- //接着看这里。
- int numAnims = animations.size();
- int i = 0;
- while (i < numAnims) {
- ValueAnimator anim = animations.get(i);
- //animationFrame方法返回true,意味着此动画已经执行完毕,
- //否则开始真正计算AnimatedValue的值,大家可以根据
- //getAnimationValue来获取这个值,在ObjectAnimator中
- //此方法还会不断设置object中的属性值
- if (anim.animationFrame(currentTime)) {
- endingAnims.add(anim);
- }
- if (animations.size() == numAnims) {
- ++i;
- } else { //这里是处理当前正在执行的动画,被cancle的情况
- // An animation might be canceled or ended by client code
- // during the animation frame. Check to see if this happened by
- // seeing whether the current index is the same as it was before
- // calling animationFrame(). Another approach would be to copy
- // animations to a temporary list and process that list instead,
- // but that entails garbage and processing overhead that would
- // be nice to avoid.
- --numAnims;
- endingAnims.remove(anim);
- }
- }
- //处理执行结束后的动画,结束后会把动画从所有集合中移除,
- //并且触发监听通知用户
- if (endingAnims.size() > 0) {
- for (i = 0; i < endingAnims.size(); ++i) {
- endingAnims.get(i).endAnimation();
- }
- endingAnims.clear();
- }
- //如果任然有活动的动画或者延迟执行的动画,会继续执行下一帧
- //执行下一帧的时间在0-10ms之间
- if (callAgain && (!animations.isEmpty() || !delayedAnims.isEmpty())) {
- sendEmptyMessageDelayed(ANIMATION_FRAME, Math.max(0, sFrameDelay -
- (AnimationUtils.currentAnimationTimeMillis() - currentTime)));
- }
- break;
- }
- }
- }
在handler逐帧更新代码中,anim.animationFrame(currentTime),是计算动画执行过程中,值的变化的,
- boolean animationFrame(long currentTime) {
- boolean done = false;
- switch (mPlayingState) {
- case RUNNING:
- case SEEKED:
- //这句代码是重点,通过currentTime和mStartTime的差值计算动画执行的进度,0-1的小数值
- float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
- if (fraction >= 1f) { //这里是处理动画是否执行完毕的逻辑,暂时可以不用看
- if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
- // Time to repeat
- if (mListeners != null) {
- int numListeners = mListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- mListeners.get(i).onAnimationRepeat(this);
- }
- }
- if (mRepeatMode == REVERSE) {
- mPlayingBackwards = mPlayingBackwards ? false : true;
- }
- mCurrentIteration += (int)fraction;
- fraction = fraction % 1f;
- mStartTime += mDuration;
- } else {
- done = true;
- fraction = Math.min(fraction, 1.0f);
- }
- }
- //真正计算animationValue和执行onAnimationUpdate回调的
- //方法在这里
- animateValue(fraction);
- break;
- }
- return done;
- }
animationValue方法通过插值器重新计算一个fraction,
- /**
- *
- *
- * @param fraction 通过总时间和已经执行时间,计算出来的动画进度
- */
- void animateValue(float fraction) {
- //通过插值器,对fraction重新计算,插值器不同计算出来的结果不同,
- //这个跟Tween动画时一样的
- fraction = mInterpolator.getInterpolation(fraction);
- mCurrentFraction = fraction;
- int numValues = mValues.length;
- for (int i = 0; i < numValues; ++i) {
- mValues[i].calculateValue(fraction); //真正计算animationValue的方法
- }
- //没一帧的执行都会执行回调,这样使用者就能获取每一帧计算出来的animationValue了
- if (mUpdateListeners != null) {
- int numListeners = mUpdateListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- mUpdateListeners.get(i).onAnimationUpdate(this);
- }
- }
- }
真正的计算是交给PropertyValuesHolder.calculateValue(float fraction)计算,之前我们看到传进来的values值已经被PropertyValuesHolder包装并保存起来了,那么现在我们就可以利用到这些值来进行计算了。
- void calculateValue(float fraction) {
- mAnimatedValue = mKeyframeSet.getValue(fraction);
- }
查看IntKeyframeSet
- public int getIntValue(float fraction) {
- if (mNumKeyframes == 2) { //当只有firstValue和lastValue时,发现最终是通过mEvaluator.evaluate来计算mAnimatedValue
- if (firstTime) {
- firstTime = false;
- firstValue = ((IntKeyframe) mKeyframes.get(0)).getIntValue();
- lastValue = ((IntKeyframe) mKeyframes.get(1)).getIntValue();
- deltaValue = lastValue - firstValue;
- }
- if (mInterpolator != null) {
- fraction = mInterpolator.getInterpolation(fraction);
- }
- //真正计算出mAnimatedValue的地方
- if (mEvaluator == null) {
- return firstValue + (int)(fraction * deltaValue);
- } else {
- return ((Number)mEvaluator.evaluate(fraction, firstValue, lastValue)).intValue();
- }
- }
- //后面这些复制的操作可以先不看,是处理类似OvershootInterpolator插值器(超过给定值,再回来),和AnticipateInterpolator,先小于给定初始值,再正常继续执行,以及BounceInterpolator,弹性动作
- if (fraction <= 0f) {
- final IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(0);
- final IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(1);
- int prevValue = prevKeyframe.getIntValue();
- int nextValue = nextKeyframe.getIntValue();
- float prevFraction = prevKeyframe.getFraction();
- float nextFraction = nextKeyframe.getFraction();
- final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
- return mEvaluator == null ?
- prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
- ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
- intValue();
- } else if (fraction >= 1f) {
- final IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(mNumKeyframes - 2);
- final IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(mNumKeyframes - 1);
- int prevValue = prevKeyframe.getIntValue();
- int nextValue = nextKeyframe.getIntValue();
- float prevFraction = prevKeyframe.getFraction();
- float nextFraction = nextKeyframe.getFraction();
- final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
- return mEvaluator == null ?
- prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
- ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).intValue();
- }
- IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(0);
- for (int i = 1; i < mNumKeyframes; ++i) {
- IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(i);
- if (fraction < nextKeyframe.getFraction()) {
- final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- float intervalFraction = (fraction - prevKeyframe.getFraction()) /
- (nextKeyframe.getFraction() - prevKeyframe.getFraction());
- int prevValue = prevKeyframe.getIntValue();
- int nextValue = nextKeyframe.getIntValue();
- return mEvaluator == null ?
- prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
- ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
- intValue();
- }
- prevKeyframe = nextKeyframe;
- }
- // shouldn't get here
- return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).intValue();
- }
看类IntEvaluator
- /**
- * 这里其实比较简单,通过startValue,endValue和fraction(动画执行的进度),计算出动画执行 *的中间值
- **/
- public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
- int startInt = startValue;
- return (int)(startInt + fraction * (endValue - startInt));
- }
这样每一帧都会计算出当前进度的animationValue,而我们根据AnimatorUpdateListener就可以获取每一帧计算过后animationValue值了。
这样关于ValueAnimator工作的基本过程就都讲清楚了。下面看看ObjectAnimator。
2.ObjectAnimator
ObjectAnimator是通过传递进来一个对象,以及对象的属性名称,在anim.start()执行过程中不断更改对象的属性值,来实现动画效果的。
前提是传递进来的对象的属性,必须要具有相应的set和get方法。
ObjectAnimator是继承自ValueAnimator,前者的许多方法其实是调用ValueAnimator的方法,所以说ValueAnimator是动画核心,因为它处理了
驱动引擎这一块。ObjectAnimator多传入了两个参数,一个是target对象(可以是任何对象,不限于View),一个是对象属性propertyName(前提是所属对象必须拥有对应的setPropertyName(),getPropertyName方法)
下面还是来看一个ObjectAnimator的简单的例子:
- ObjectAnimator anm = ObjectAnimator.ofFloat(myView, "alpha", 1);
- anm.setDuration(200);
- anm.start();
代码的作用是对View的alpha值进行更改,注意这里可以只提供一个value值,而ValueAnimator则必须提供两个值以上。这是因为:这里提供的一个值是作为
endValue,startValue则是通过myView.getAlpha()来获得。下面再来看看ObjectAnimator.ofFloat()方法:
- public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
- ObjectAnimator anim = new ObjectAnimator(target, propertyName);
- anim.setFloatValues(values);
- return anim;
- }
注意看,这里实例化ObjectAnimator多传入了target对象和其对于的属性名称propertyName,这里的作用是在动画改变的过程中,不断通过对象的setPropertyName方法改变PropertyName的值,
在样在不断的重绘过程中获得新的值,就能实现动画效果了。当然View提供的set方法可能稍微更复杂一些,不过意思还是一样的。
下面继续看代码:
- private ObjectAnimator(Object target, String propertyName) {
- mTarget = target;
- setPropertyName(propertyName);
- }
再看setFloatValues方法
- public void setFloatValues(float... values) {
- //第一次初始化时,mValues肯定为null,这里初始化它
- if (mValues == null || mValues.length == 0) {
- // No values yet - this animator is being constructed piecemeal. Init the values with
- // whatever the current propertyName is
- if (mProperty != null) {
- setValues(PropertyValuesHolder.ofFloat(mProperty, values));
- } else {
- //之前我们说过提供的值都被保存到PropertyValuesHolder
- //这里还提供了propertyName,标志改变的是哪个属性的值
- //在初始化set,get方法实例时会被调用
- setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));
- }
- } else {
- super.setFloatValues(values);
- }
- }
后续的setDuration,start动画,都和ValueAnimator一样,执行的流程都是相同的,不同的是ObjectAnimator重写了几个方法,让其执行了更多的操作,我们依次来看看重写了哪几个方法,
首先是重写了initAnimation(),此方法会在动画执行之前调用。
- @Override
- void initAnimation() {
- if (!mInitialized) {
- //果然在PropertyValuesHolder中实例化了mTarget对象的对应
- //属性的set,get方法,propertyName已经在实例化PropertyValuesHolder
- //的时候传递给了它。
- int numValues = mValues.length;
- for (int i = 0; i < numValues; ++i) {
- mValues[i].setupSetterAndGetter(mTarget);
- }
- super.initAnimation();
- }
- }
现在具体看下setUpSetterAndGetter的实现细节
- void setupSetterAndGetter(Object target) {
- Class targetClass = target.getClass();
- if (mSetter == null) {
- setupSetter(targetClass); //初始化setter方法
- }
- //之前在ValueAnimator中说过,一个keyFrame对应于一个传进来的
- //value值,如果values值没有设置,会在这里调用get方法设置startValue
- for (Keyframe kf : mKeyframeSet.mKeyframes) {
- if (!kf.hasValue()) {
- if (mGetter == null) { //初始化getter方法
- setupGetter(targetClass);
- }
- try {
- //通过get方法设置startValue
- kf.setValue(mGetter.invoke(target));
- } catch (InvocationTargetException e) {
- Log.e("PropertyValuesHolder", e.toString());
- } catch (IllegalAccessException e) {
- Log.e("PropertyValuesHolder", e.toString());
- }
- }
- }
- }
下面是set,get方法具体实现
- void setupSetter(Class targetClass) {
- mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", mValueType);
- }
- private void setupGetter(Class targetClass) {
- mGetter = setupSetterOrGetter(targetClass, sGetterPropertyMap, "get", null);
- }
- /**
- *
- * @param targetClass 传入的target对应的class对象
- * @param propertyMapMap 这是静态集合,缓存所有ObjectAnimator中target对应的set,get方法
- * @param prefix set或get前缀
- * @param valueType set方法对应的参数类型
- * @return
- */
- private Method setupSetterOrGetter(Class targetClass,
- HashMap<Class, HashMap<String, Method>> propertyMapMap,
- String prefix, Class valueType) {
- Method setterOrGetter = null;
- try {
- // Have to lock property map prior to reading it, to guard against
- // another thread putting something in there after we've checked it
- // but before we've added an entry to it
- mPropertyMapLock.writeLock().lock();
- //先从缓存查看
- HashMap<String, Method> propertyMap = propertyMapMap.get(targetClass);
- if (propertyMap != null) {
- setterOrGetter = propertyMap.get(mPropertyName);
- }
- if (setterOrGetter == null) {
- //真正用反射获取set,get方法Method实例的地方
- setterOrGetter = getPropertyFunction(targetClass, prefix, valueType);
- if (propertyMap == null) {
- propertyMap = new HashMap<String, Method>();
- propertyMapMap.put(targetClass, propertyMap);
- }
- //缓存到集合
- propertyMap.put(mPropertyName, setterOrGetter);
- }
- } finally {
- mPropertyMapLock.writeLock().unlock();
- }
- return setterOrGetter;
- }
- private Method getPropertyFunction(Class targetClass, String prefix, Class valueType) {
- // TODO: faster implementation...
- Method returnVal = null;
- //根据前缀set或get,和传入的mPropertyName组合成方法名
- //比如alpha会组合成setAlpha和getAlpha
- String methodName = getMethodName(prefix, mPropertyName);
- Class args[] = null;
- if (valueType == null) { //无参数,这是get方法
- try {
- returnVal = targetClass.getMethod(methodName, args);
- } catch (NoSuchMethodException e) {
- Log.e("PropertyValuesHolder",
- "Couldn't find no-arg method for property " + mPropertyName + ": " + e);
- }
- } else {
- //获得set方法Method对象,这里稍微复杂一点,其实也很简单,就是重试了多次,选定多个参数
- //type类型,防止一出错就放弃了,
- args = new Class[1];
- Class typeVariants[];
- if (mValueType.equals(Float.class)) {
- typeVariants = FLOAT_VARIANTS;
- } else if (mValueType.equals(Integer.class)) {
- typeVariants = INTEGER_VARIANTS;
- } else if (mValueType.equals(Double.class)) {
- typeVariants = DOUBLE_VARIANTS;
- } else {
- typeVariants = new Class[1];
- typeVariants[0] = mValueType;
- }
- for (Class typeVariant : typeVariants) {
- args[0] = typeVariant;
- try {
- returnVal = targetClass.getMethod(methodName, args);
- // change the value type to suit
- mValueType = typeVariant;
- return returnVal;
- } catch (NoSuchMethodException e) {
- // Swallow the error and keep trying other variants
- }
- }
- }
- return returnVal;
- }
至此,set和get方法的初始化和缓存就全部结束了。
再看ValueAnimator重写的另一个方法animateValue
- /**
- * 在ValueAnimator中知道,animateValue是在动画执行过程中,
- * 在animationFrame中执行的,这里除了执行父类的animateValue,
- * 计算每一帧得到的animationValue值,还把这个值通过setAnimatedValue
- * 设置到了目标对象的属性中
- * @param fraction
- */
- @Override
- void animateValue(float fraction) {
- super.animateValue(fraction);
- int numValues = mValues.length;
- for (int i = 0; i < numValues; ++i) {
- //通过此方法,把父类计算出的animationValue
- //通过set方法设置目标对象传入的属性中
- mValues[i].setAnimatedValue(mTarget);
- }
- }
看看其具体实现
- void setAnimatedValue(Object target) {
- if (mSetter != null) {
- try {
- mTmpValueArray[0] = getAnimatedValue();
- //反射执行set方法,传入每一帧计算得到的AnimatedValue值
- mSetter.invoke(target, mTmpValueArray);
- } catch (InvocationTargetException e) {
- Log.e("PropertyValuesHolder", e.toString());
- } catch (IllegalAccessException e) {
- Log.e("PropertyValuesHolder", e.toString());
- }
- }
- }
到这里具体的实现就基本完成了,我们看到ObjectAnimator与ValueAnimator只有3个地方不同,
其一是提供了Object对象,以及对象的propertyName
其二是重写initAnimation方法,额外初始化了对应属性的set和get方法
其三就是重写animateValue,把每一帧计算的到的中间值通过set方法传入对象属性中。
ObjectAnimator实现基本就是这些东西。
3.更多
如果ValueAnimator要传入多个属性值有这几种方法
- 1.Multiple ObjectAnimator objects
- ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
- ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
- AnimatorSet animSetXY = new AnimatorSet();
- animSetXY.playTogether(animX, animY);
- animSetXY.start();
- 2.One ObjectAnimator
- PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
- PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
- ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
- ViewPropertyAnimator
- 3. //这是view独有的
- myView.animate().x(50f).y(100f);
如果要多次改变动画效果,可以直接设置keyFrame,
- //前半段从0变到360度,后半段从360度变回0度
- Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
- Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
- Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
- PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
- ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
- rotationAnim.setDuration(5000ms);