Search code examples
androidanimationandroid-animationscale

AnimationSet with setStartOffset not working


I'm trying to run few animations (one after another) on a view using AnimationSet

Scale from 1 --> 0 and than from 0 --> 1

AnimationSet animationSet = new AnimationSet(true);
animationSet.setInterpolator(new AccelerateDecelerateInterpolator());

ScaleAnimation animation1 = new ScaleAnimation(1f, 0f, 1f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation1.setDuration(500);

ScaleAnimation animation2 = new ScaleAnimation(0f, 1f, 0f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation2.setDuration(500);
animation2.setStartOffset(500);

animationSet.addAnimation(animation1);
animationSet.addAnimation(animation2);

mFloatingActionButton.startAnimation(animationSet);

The view just disappear and after a sec appear again. No animation.

If I remove the setStartOffset(...) I can see animation, but not the one I want.

What am I missing here?


Solution

  • Chaining animations using start offset rarely behaves as expected. There are several ways to achieve the effect you want:

    1) Using ScaleAnimations, you chain the animations using listeners (start the second animation on the onAnimationEnd callback).

    2) Using animatorSets (as opposed to animationSets) with playSequentially.

    Simplified code for option 1:

    final View theView = findViewById(R.id.the_view);
    final ScaleAnimation scaleAnimation1 = new ScaleAnimation(1,0,1,0);
    final ScaleAnimation scaleAnimation2 = new ScaleAnimation(0,1,0,1);
    scaleAnimation1.setAnimationListener(new Animation.AnimationListener()
    {
        @Override
        public void onAnimationStart(Animation animation)
        {
        }
         @Override
        public void onAnimationEnd(Animation animation)
        {
            theView.startAnimation(scaleAnimation2);
        }
         @Override
        public void onAnimationRepeat(Animation animation)
        {
        }
    });
    

    Simplified code for option 2:

    final View theView = findViewById(R.id.the_view);
    
    ObjectAnimator animScaleXSmaller = ObjectAnimator.ofFloat(theView, "scaleX", 0f);
    ObjectAnimator animScaleYSmaller = ObjectAnimator.ofFloat(theView, "scaleY", 0f);
    AnimatorSet animScaleXYSmaller = new AnimatorSet();
    animScaleXYSmaller.setDuration(500);
    animScaleXYSmaller.playTogether(animScaleXSmaller, animScaleYSmaller);
    
    ObjectAnimator animScaleXBigger = ObjectAnimator.ofFloat(theView, "scaleX", 1f);
    ObjectAnimator animScaleYBigger = ObjectAnimator.ofFloat(theView, "scaleY", 1f);
    AnimatorSet animScaleXYBigger = new AnimatorSet();
    animScaleXYBigger.setDuration(500);
    animScaleXYBigger.playTogether(animScaleXBigger, animScaleYBigger);
    
    AnimatorSet animScaleBounce = new AnimatorSet();
    animScaleBounce.playSequentially(animScaleXYSmaller, animScaleXYBigger);
    animScaleBounce.setInterpolator(new AccelerateDecelerateInterpolator());
    animScaleBounce.start();