Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 010dbaa1 authored by Chet Haase's avatar Chet Haase
Browse files

Fix bugs in Sequencer

Change-Id: I03aebe8d822bef0b9e163ba3280699ca02a6563c
parent e8466b3f
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -28,8 +28,13 @@ import java.util.ArrayList;
 * This class provides a simple timing engine for running animations
 * which calculate animated values and set them on target objects.
 *
 * There is a single timing pulse that all animations use. It runs in a
 * custom handler to ensure that property changes happen on the UI thread.
 * <p>There is a single timing pulse that all animations use. It runs in a
 * custom handler to ensure that property changes happen on the UI thread.</p>
 *
 * <p>By default, Animator uses non-linear time interpolation, via the
 * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates
 * out of an animation. This behavior can be changed by calling
 * {@link Animator#setInterpolator(Interpolator)}.</p>
 */
public class Animator extends Animatable {

+31 −24
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ import java.util.HashMap;
 * either the {@link Sequencer#playTogether(Animatable...) playTogether()} or
 * {@link Sequencer#playSequentially(Animatable...) playSequentially()} methods can be called to add
 * a set of animations all at once, or the {@link Sequencer#play(Animatable)} can be
 * used in conjunction with methods in the {@link android.animation.Sequencer.Builder Builder}
 * used in conjunction with methods in the {@link myandroid.animation.Sequencer.Builder Builder}
 * class to add animations
 * one by one.</p>
 *
@@ -82,6 +82,13 @@ public final class Sequencer extends Animatable {

    private SequencerAnimatableListener mSequenceListener = null;

    /**
     * Flag indicating that the Sequencer has been canceled (by calling cancel() or end()).
     * This flag is used to avoid starting other animations when currently-playing
     * child animations of this Sequencer end.
     */
    boolean mCanceled = false;

    /**
     * Sets up this Sequencer to play all of the supplied animations at the same time.
     *
@@ -161,6 +168,7 @@ public final class Sequencer extends Animatable {
    @SuppressWarnings("unchecked")
    @Override
    public void cancel() {
        mCanceled = true;
        if (mListeners != null) {
            ArrayList<AnimatableListener> tmpListeners =
                    (ArrayList<AnimatableListener>) mListeners.clone();
@@ -168,11 +176,10 @@ public final class Sequencer extends Animatable {
                listener.onAnimationCancel(this);
            }
        }
        if (mPlayingSet.size() > 0) {
            for (Animatable item : mPlayingSet) {
                item.cancel();
        if (mSortedNodes.size() > 0) {
            for (Node node : mSortedNodes) {
                node.animation.cancel();
            }
            mPlayingSet.clear();
        }
    }

@@ -184,11 +191,11 @@ public final class Sequencer extends Animatable {
     */
    @Override
    public void end() {
        if (mPlayingSet.size() > 0) {
            for (Animatable item : mPlayingSet) {
                item.end();
        mCanceled = true;
        if (mSortedNodes.size() > 0) {
            for (Node node : mSortedNodes) {
                node.animation.end();
            }
            mPlayingSet.clear();
        }
    }

@@ -202,6 +209,8 @@ public final class Sequencer extends Animatable {
    @SuppressWarnings("unchecked")
    @Override
    public void start() {
        mCanceled = false;

        // First, sort the nodes (if necessary). This will ensure that sortedNodes
        // contains the animation nodes in the correct order.
        sortNodes();
@@ -221,7 +230,7 @@ public final class Sequencer extends Animatable {
            } else {
                for (Dependency dependency : node.dependencies) {
                    dependency.node.animation.addListener(
                            new DependencyListener(node, dependency.rule));
                            new DependencyListener(this, node, dependency.rule));
                }
                node.tmpDependencies = (ArrayList<Dependency>) node.dependencies.clone();
            }
@@ -247,6 +256,8 @@ public final class Sequencer extends Animatable {
     */
    private static class DependencyListener implements AnimatableListener {

        private Sequencer mSequencer;

        // The node upon which the dependency is based.
        private Node mNode;

@@ -254,27 +265,18 @@ public final class Sequencer extends Animatable {
        // the node
        private int mRule;

        public DependencyListener(Node node, int rule) {
        public DependencyListener(Sequencer sequencer, Node node, int rule) {
            this.mSequencer = sequencer;
            this.mNode = node;
            this.mRule = rule;
        }

        /**
         * If an animation that is being listened for is canceled, then this removes
         * the listener on that animation, to avoid triggering further animations down
         * the line when the animation ends.
         * Ignore cancel events for now. We may want to handle this eventually,
         * to prevent follow-on animations from running when some dependency
         * animation is canceled.
         */
        public void onAnimationCancel(Animatable animation) {
            Dependency dependencyToRemove = null;
            for (Dependency dependency : mNode.tmpDependencies) {
                if (dependency.node.animation == animation) {
                    // animation canceled - remove the dependency and listener
                    dependencyToRemove = dependency;
                    animation.removeListener(this);
                    break;
                }
            }
            mNode.tmpDependencies.remove(dependencyToRemove);
        }

        /**
@@ -308,6 +310,10 @@ public final class Sequencer extends Animatable {
         * @param dependencyAnimation the animation that sent the event.
         */
        private void startIfReady(Animatable dependencyAnimation) {
            if (mSequencer.mCanceled) {
                // if the parent Sequencer was canceled, then don't start any dependent anims
                return;
            }
            Dependency dependencyToRemove = null;
            for (Dependency dependency : mNode.tmpDependencies) {
                if (dependency.rule == mRule &&
@@ -405,6 +411,7 @@ public final class Sequencer extends Animatable {
                        }
                    }
                }
                roots.clear();
                roots.addAll(tmpRoots);
                tmpRoots.clear();
            }