JMRboosties
JMRboosties

Reputation: 15740

Android LayoutAnimationController: How to force the first child to wait for the last child's animation to finish before repeating?

I'm trying to build an animation where this image:

No bars

Becomes this image:

Bars

Where the three bars fade in like 1...2...3... then back to none. At this point the animation will repeat. Here is what I tried to make work:

    AlphaAnimation anim = (AlphaAnimation) AnimationUtils.loadAnimation(this, R.anim.fade_in);
    anim.setRepeatMode(Animation.RESTART);
    anim.setRepeatCount(Animation.INFINITE);
    anim.setStartOffset(3000);

    LayoutAnimationController controller = new LayoutAnimationController(anim, 0.5f);

    rl.setLayoutAnimation(controller);

    rl.startLayoutAnimation();

This almost works, but the problem is that the first child in the view group of those wifi bars doesn't wait for the last child to complete its animation before it goes off. The result is a beat that looks like 1...2...3..1..2.3...1...3...1..2.3 instead of a nice 1..2..3..1..2..3. I need to find a way to make the controller wait until the cycle is completed before setting the 1st child off again. I haven't been able to find any solutions on this, does anyone have some input? I'm open to changing the way I'm doing this altogether, this LayoutAnimationController class just seemed to be the best way up until this point.

Thanks!

Upvotes: 4

Views: 1829

Answers (1)

Alin
Alin

Reputation: 14571

When I had to use an animation for a image, I prepared the frames. I used AnimatioDrawable with this class:

* This class is a hack to simply get an on finish callback for an
* AnimationDrawable.
*
*/
public class CustomAnimationDrawable extends AnimationDrawable {
// We need to keep our own frame count because mCurFrame in AnimationDrawable is private
private int mCurFrameHack = -1;

// This is the Runnable that we will call when the animation finishes
private Runnable mCallback = null;

/*
* We override the run method in order to increment the frame count the same
* way the AnimationDrawable class does. Also, when we are on the last frame we
* schedule our callback to be called after the duration of the last frame.
*/
@Override
public void run() {
super.run();

mCurFrameHack += 1;
if (mCurFrameHack == (getNumberOfFrames() - 1) && mCallback != null) {
scheduleSelf(mCallback, SystemClock.uptimeMillis() + getDuration(mCurFrameHack));
}
}

/*
* We override this method simply to reset the frame count just as is done in
* AnimationDrawable.
*/
@Override
public void unscheduleSelf(Runnable what) {
// TODO Auto-generated method stub
super.unscheduleSelf(what);
mCurFrameHack = -1;
}

public void setOnFinishCallback(Runnable callback) {
mCallback = callback;
}

public Runnable getOnFinishCallback() {
return mCallback;
}

}

And in my code I use it like:

        CustomAnimationDrawable staticAnimation = new CustomAnimationDrawable();
    //add frames with resources and duration. step is just a class of mine
        staticAnimation.addFrame(getResources().getDrawable(step.getStepImageResId()), step.getStepDuration());
    staticAnimation.addFrame(getResources().getDrawable(step.getStepImageResId()), step.getStepDuration());
    staticAnimation.addFrame(getResources().getDrawable(step.getStepImageResId()), step.getStepDuration());
        staticAnimation.setOneShot(false);

        imgView.setBackgroundDrawable(staticAnimation);
staticAnimation.start();

Probably not the best solution out there, but it worked for my needs.

Upvotes: 2

Related Questions