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

Commit 358af100 authored by Chet Haase's avatar Chet Haase Committed by Android (Google) Code Review
Browse files

Merge "Fix bugs in Sequencer"

parents 3f15301c 010dbaa1
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();
            }