Android animation开发笔记

来源:互联网 发布:发那科机器人编程培训 编辑:程序博客网 时间:2024/06/08 18:23

最近的工作涉及到Android的animation开发,学到了一些之前没有注意到的知识点,作个记录。

fillEnable、fillBefore和fillAfter

Animation的fillBefore和fillAfter属性分别用来控制动画开始之前或者播放完毕时是否将transformation作用到视图上,默认情况下它们的值分别为true和false。
如果在xml文件中将fillAfter设置为true,那么在动画播放完毕后,视图会停留在动画的最后一个状态,这种效果是符合预期的。但是如果将fillBefore设置为false同时
设置了startOffset,就会发现在动画真正开始前视图就已经处于动画的第一个状态,也就意味着fillBefore=false不起作用。按照官方文档的说明,fillBefore=false
只有在fillEnable被设置为true的情况下才会起作用。为何会出现这种奇怪的问题?从源代码中可以找到答案。以下是Animation的getTransformation函数中的几行代码:

final long startOffset = getStartOffset();   final long duration = mDuration;   float normalizedTime;   if (duration != 0) {       normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /               (float) duration;   } else {       // time is a step-change with a zero duration       normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;   }   final boolean expired = normalizedTime >= 1.0f;   mMore = !expired;   if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);   if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {       if (!mStarted) {           fireAnimationStart();           mStarted = true;           if (USE_CLOSEGUARD) {               guard.open("cancel or detach or getTransformation");           }       }       if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);       if (mCycleFlip) {           normalizedTime = 1.0f - normalizedTime;       }       final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);       applyTransformation(interpolatedTime, outTransformation);   }

从代码中可以看到当设置了startOffset而当前时间还没到动画真正播放时间时,变量normalizedTime是一个负值。接下来分两种情况讨论:

  1. 仅仅设置了fillBefore=false

    此时fillEnable为默认值false,因此

    if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);

    这个if条件满足,从而使得normalizedTime被设置为0,进而使得接下来的if条件也能满足,虽然此时fillBefore=false,但怎奈normalizedTime已被设置成了0.
    而在这个if语句块中调用了函数applyTransformation。

  2. 设置了fillBefore=false同时fillEnable=true

    这意味着上面的if语句块不会被执行,因此动画播放前normalizedTime始终为负值,那么接下来的if语句块也不会被执行了。

AnimationSet的repeatCount

想让一个动画循环播放,一个简单的方法是在xml文件中将动画的repeatCount属性设置为“infinite”。但是这个方法只能应用于单一动画,如< translate >、< scale >等等,
对< set >却无效。目前的解决方法是给Animation设置一个AnimationListener,在onAnimationEnd方法中调用View.startAnimation(animation)重新播放动画。

0 0
原创粉丝点击