AnimatorSet.java revision 7c608f25d494c8a0a671e7373efbb47ca635367e
117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase/* 217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Copyright (C) 2010 The Android Open Source Project 317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * you may not use this file except in compliance with the License. 617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * You may obtain a copy of the License at 717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * http://www.apache.org/licenses/LICENSE-2.0 917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 1017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Unless required by applicable law or agreed to in writing, software 1117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * distributed under the License is distributed on an "AS IS" BASIS, 1217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * See the License for the specific language governing permissions and 1417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * limitations under the License. 1517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 1617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 1717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haasepackage android.animation; 1817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 1917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haaseimport java.util.ArrayList; 2017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haaseimport java.util.HashMap; 2117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 2217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase/** 23a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * This class plays a set of {@link Animator} objects in the specified order. Animations 2417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * can be set up to play together, in sequence, or after a specified delay. 2517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 26a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>There are two different approaches to adding animations to a <code>AnimatorSet</code>: 27a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * either the {@link AnimatorSet#playTogether(Animator[]) playTogether()} or 28a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#playSequentially(Animator[]) playSequentially()} methods can be called to add 29a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * a set of animations all at once, or the {@link AnimatorSet#play(Animator)} can be 30a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * used in conjunction with methods in the {@link AnimatorSet.Builder Builder} 3117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * class to add animations 3217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * one by one.</p> 3317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 34a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>It is possible to set up a <code>AnimatorSet</code> with circular dependencies between 3517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * its animations. For example, an animation a1 could be set up to start before animation a2, a2 3617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * before a3, and a3 before a1. The results of this configuration are undefined, but will typically 3717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * result in none of the affected animations being played. Because of this (and because 3817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * circular dependencies do not make logical sense anyway), circular dependencies 3917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * should be avoided, and the dependency flow of animations should only be in one direction. 4017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 41a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haasepublic final class AnimatorSet extends Animator { 4217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 4317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 4449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * Internal variables 4549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * NOTE: This object implements the clone() method, making a deep copy of any referenced 4649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * objects. As other non-trivial fields are added to this class, make sure to add logic 4749afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * to clone() to make deep copies of them. 4849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase */ 4949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase 5049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase /** 513b69b6f0be85d1f97c1e6824cf986777ba4e5d00Chet Haase * Tracks animations currently being played, so that we know what to 52a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * cancel or end when cancel() or end() is called on this AnimatorSet 5317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 54a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private ArrayList<Animator> mPlayingSet = new ArrayList<Animator>(); 5517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 5617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 57a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Contains all nodes, mapped to their respective Animators. When new 58a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * dependency information is added for an Animator, we want to add it 59a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * to a single node representing that Animator, not create a new Node 6017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * if one already exists. 6117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 62a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private HashMap<Animator, Node> mNodeMap = new HashMap<Animator, Node>(); 6317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 6417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 65a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Set of all nodes created for this AnimatorSet. This list is used upon 66a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * starting the set, and the nodes are placed in sorted order into the 6717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * sortedNodes collection. 6817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 6949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase private ArrayList<Node> mNodes = new ArrayList<Node>(); 7017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 7117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 7217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * The sorted list of nodes. This is the order in which the animations will 7317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * be played. The details about when exactly they will be played depend 7417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * on the dependency relationships of the nodes. 7517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 7649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase private ArrayList<Node> mSortedNodes = new ArrayList<Node>(); 7717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 7817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 7917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Flag indicating whether the nodes should be sorted prior to playing. This 8017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * flag allows us to cache the previous sorted nodes so that if the sequence 8117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * is replayed with no changes, it does not have to re-sort the nodes again. 8217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 8317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private boolean mNeedsSort = true; 8417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 85a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private AnimatorSetListener mSetListener = null; 8617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 8717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 88a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Flag indicating that the AnimatorSet has been canceled (by calling cancel() or end()). 89010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase * This flag is used to avoid starting other animations when currently-playing 90a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * child animations of this AnimatorSet end. 91010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase */ 92010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase boolean mCanceled = false; 93010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase 9421cd1389d2ef218b20994b617c57af120841a57fChet Haase // The amount of time in ms to delay starting the animation after start() is called 9521cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mStartDelay = 0; 9621cd1389d2ef218b20994b617c57af120841a57fChet Haase 9721cd1389d2ef218b20994b617c57af120841a57fChet Haase 9821cd1389d2ef218b20994b617c57af120841a57fChet Haase // How long the child animations should last in ms. The default value is negative, which 99a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // simply means that there is no duration set on the AnimatorSet. When a real duration is 10021cd1389d2ef218b20994b617c57af120841a57fChet Haase // set, it is passed along to the child animations. 10121cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mDuration = -1; 10221cd1389d2ef218b20994b617c57af120841a57fChet Haase 10321cd1389d2ef218b20994b617c57af120841a57fChet Haase 104010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase /** 105a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Sets up this AnimatorSet to play all of the supplied animations at the same time. 10617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 107a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @param items The animations that will be started simultaneously. 10817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 109a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void playTogether(Animator... items) { 110a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (items != null) { 11117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNeedsSort = true; 112a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase Builder builder = play(items[0]); 113a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase for (int i = 1; i < items.length; ++i) { 114a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase builder.with(items[i]); 11517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 11617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 11717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 11817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 11917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 120a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Sets up this AnimatorSet to play each of the supplied animations when the 12117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * previous animation ends. 12217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 123a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @param items The aniamtions that will be started one after another. 12417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 125a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void playSequentially(Animator... items) { 126a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (items != null) { 12717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNeedsSort = true; 128a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (items.length == 1) { 129a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase play(items[0]); 13017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } else { 131a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase for (int i = 0; i < items.length - 1; ++i) { 132a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase play(items[i]).before(items[i+1]); 13317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 13417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 13517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 13617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 13717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 13817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 139a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Returns the current list of child Animator objects controlled by this 140a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet. This is a copy of the internal list; modifications to the returned list 141a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * will not affect the AnimatorSet, although changes to the underlying Animator objects 142a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * will affect those objects being managed by the AnimatorSet. 143f54a8d7c479485174941c38f151ea7083c658da3Chet Haase * 144a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @return ArrayList<Animator> The list of child animations of this AnimatorSet. 145f54a8d7c479485174941c38f151ea7083c658da3Chet Haase */ 146a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public ArrayList<Animator> getChildAnimations() { 147a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ArrayList<Animator> childList = new ArrayList<Animator>(); 148f54a8d7c479485174941c38f151ea7083c658da3Chet Haase for (Node node : mNodes) { 149f54a8d7c479485174941c38f151ea7083c658da3Chet Haase childList.add(node.animation); 150f54a8d7c479485174941c38f151ea7083c658da3Chet Haase } 151f54a8d7c479485174941c38f151ea7083c658da3Chet Haase return childList; 152f54a8d7c479485174941c38f151ea7083c658da3Chet Haase } 153f54a8d7c479485174941c38f151ea7083c658da3Chet Haase 154f54a8d7c479485174941c38f151ea7083c658da3Chet Haase /** 155811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase * Sets the target object for all current {@link #getChildAnimations() child animations} 156a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * of this AnimatorSet that take targets ({@link ObjectAnimator} and 157a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet). 158811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase * 159811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase * @param target The object being animated 160811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase */ 16121cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 162811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase public void setTarget(Object target) { 163811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase for (Node node : mNodes) { 164a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase Animator animation = node.animation; 165a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (animation instanceof AnimatorSet) { 166a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ((AnimatorSet)animation).setTarget(target); 167a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase } else if (animation instanceof ObjectAnimator) { 168a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ((ObjectAnimator)animation).setTarget(target); 169811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase } 170811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase } 171811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase } 172811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase 173811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase /** 174e0ee2e9f3102c3c14c873a75a7b04e49787e0fb9Chet Haase * Sets the TimeInterpolator for all current {@link #getChildAnimations() child animations} 175a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * of this AnimatorSet. 17621cd1389d2ef218b20994b617c57af120841a57fChet Haase * 177a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @param interpolator the interpolator to be used by each child animation of this AnimatorSet 17821cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 17921cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 180e0ee2e9f3102c3c14c873a75a7b04e49787e0fb9Chet Haase public void setInterpolator(TimeInterpolator interpolator) { 18121cd1389d2ef218b20994b617c57af120841a57fChet Haase for (Node node : mNodes) { 18221cd1389d2ef218b20994b617c57af120841a57fChet Haase node.animation.setInterpolator(interpolator); 18321cd1389d2ef218b20994b617c57af120841a57fChet Haase } 18421cd1389d2ef218b20994b617c57af120841a57fChet Haase } 18521cd1389d2ef218b20994b617c57af120841a57fChet Haase 18621cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 18717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * This method creates a <code>Builder</code> object, which is used to 18817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * set up playing constraints. This initial <code>play()</code> method 18917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * tells the <code>Builder</code> the animation that is the dependency for 19017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * the succeeding commands to the <code>Builder</code>. For example, 191a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * calling <code>play(a1).with(a2)</code> sets up the AnimatorSet to play 19217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>a1</code> and <code>a2</code> at the same time, 193a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <code>play(a1).before(a2)</code> sets up the AnimatorSet to play 19417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>a1</code> first, followed by <code>a2</code>, and 195a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <code>play(a1).after(a2)</code> sets up the AnimatorSet to play 19617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>a2</code> first, followed by <code>a1</code>. 19717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 19817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p>Note that <code>play()</code> is the only way to tell the 19917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>Builder</code> the animation upon which the dependency is created, 20017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * so successive calls to the various functions in <code>Builder</code> 20117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * will all refer to the initial parameter supplied in <code>play()</code> 20217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * as the dependency of the other animations. For example, calling 20317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>play(a1).before(a2).before(a3)</code> will play both <code>a2</code> 20417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * and <code>a3</code> when a1 ends; it does not set up a dependency between 20517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>a2</code> and <code>a3</code>.</p> 20617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 20717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param anim The animation that is the dependency used in later calls to the 20817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * methods in the returned <code>Builder</code> object. A null parameter will result 20917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * in a null <code>Builder</code> return value. 210a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @return Builder The object that constructs the AnimatorSet based on the dependencies 21117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * outlined in the calls to <code>play</code> and the other methods in the 21217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>Builder</code object. 21317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 214a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public Builder play(Animator anim) { 21517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (anim != null) { 21617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNeedsSort = true; 21717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase return new Builder(anim); 21817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 21917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase return null; 22017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 22117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 22217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 22317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * {@inheritDoc} 22417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 225a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>Note that canceling a <code>AnimatorSet</code> also cancels all of the animations that it is 22617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * responsible for.</p> 22717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 22817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @SuppressWarnings("unchecked") 22917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @Override 23017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public void cancel() { 231010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase mCanceled = true; 23217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mListeners != null) { 233a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ArrayList<AnimatorListener> tmpListeners = 234a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase (ArrayList<AnimatorListener>) mListeners.clone(); 235a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase for (AnimatorListener listener : tmpListeners) { 23617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase listener.onAnimationCancel(this); 23717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 23817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 239010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase if (mSortedNodes.size() > 0) { 240010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase for (Node node : mSortedNodes) { 241010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase node.animation.cancel(); 24217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 24317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 24417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 24517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 24617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 24717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * {@inheritDoc} 24817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 249a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>Note that ending a <code>AnimatorSet</code> also ends all of the animations that it is 25017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * responsible for.</p> 25117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 25217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @Override 25317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public void end() { 254010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase mCanceled = true; 255f1b9b464216d2fac634be9c6aa8605d7c9ed5b68Chet Haase if (mSortedNodes.size() != mNodes.size()) { 256f1b9b464216d2fac634be9c6aa8605d7c9ed5b68Chet Haase // hasn't been started yet - sort the nodes now, then end them 257f1b9b464216d2fac634be9c6aa8605d7c9ed5b68Chet Haase sortNodes(); 2581e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase for (Node node : mSortedNodes) { 259a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (mSetListener == null) { 260a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase mSetListener = new AnimatorSetListener(this); 2611e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase } 262a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase node.animation.addListener(mSetListener); 2631e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase } 264f1b9b464216d2fac634be9c6aa8605d7c9ed5b68Chet Haase } 265010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase if (mSortedNodes.size() > 0) { 266010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase for (Node node : mSortedNodes) { 267010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase node.animation.end(); 26817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 26917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 27017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 27117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 27217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 273a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Returns true if any of the child animations of this AnimatorSet have been started and have not 274673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase * yet ended. 275a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @return Whether this AnimatorSet has been started and has not yet ended. 276673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase */ 277673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase @Override 278673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase public boolean isRunning() { 279673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase for (Node node : mNodes) { 280673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase if (node.animation.isRunning()) { 281673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase return true; 282673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase } 283673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase } 284673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase return false; 285673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase } 286673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase 287673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase /** 28821cd1389d2ef218b20994b617c57af120841a57fChet Haase * The amount of time, in milliseconds, to delay starting the animation after 28921cd1389d2ef218b20994b617c57af120841a57fChet Haase * {@link #start()} is called. 29021cd1389d2ef218b20994b617c57af120841a57fChet Haase * 29121cd1389d2ef218b20994b617c57af120841a57fChet Haase * @return the number of milliseconds to delay running the animation 29221cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 29321cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 29421cd1389d2ef218b20994b617c57af120841a57fChet Haase public long getStartDelay() { 29521cd1389d2ef218b20994b617c57af120841a57fChet Haase return mStartDelay; 29621cd1389d2ef218b20994b617c57af120841a57fChet Haase } 29721cd1389d2ef218b20994b617c57af120841a57fChet Haase 29821cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 29921cd1389d2ef218b20994b617c57af120841a57fChet Haase * The amount of time, in milliseconds, to delay starting the animation after 30021cd1389d2ef218b20994b617c57af120841a57fChet Haase * {@link #start()} is called. 30121cd1389d2ef218b20994b617c57af120841a57fChet Haase 30221cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param startDelay The amount of the delay, in milliseconds 30321cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 30421cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 30521cd1389d2ef218b20994b617c57af120841a57fChet Haase public void setStartDelay(long startDelay) { 30621cd1389d2ef218b20994b617c57af120841a57fChet Haase mStartDelay = startDelay; 30721cd1389d2ef218b20994b617c57af120841a57fChet Haase } 30821cd1389d2ef218b20994b617c57af120841a57fChet Haase 30921cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 310a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Gets the length of each of the child animations of this AnimatorSet. This value may 311a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * be less than 0, which indicates that no duration has been set on this AnimatorSet 31221cd1389d2ef218b20994b617c57af120841a57fChet Haase * and each of the child animations will use their own duration. 31321cd1389d2ef218b20994b617c57af120841a57fChet Haase * 31421cd1389d2ef218b20994b617c57af120841a57fChet Haase * @return The length of the animation, in milliseconds, of each of the child 315a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * animations of this AnimatorSet. 31621cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 31721cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 31821cd1389d2ef218b20994b617c57af120841a57fChet Haase public long getDuration() { 31921cd1389d2ef218b20994b617c57af120841a57fChet Haase return mDuration; 32021cd1389d2ef218b20994b617c57af120841a57fChet Haase } 32121cd1389d2ef218b20994b617c57af120841a57fChet Haase 32221cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 323a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Sets the length of each of the current child animations of this AnimatorSet. By default, 324a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * each child animation will use its own duration. If the duration is set on the AnimatorSet, 32521cd1389d2ef218b20994b617c57af120841a57fChet Haase * then each child animation inherits this duration. 32621cd1389d2ef218b20994b617c57af120841a57fChet Haase * 32721cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param duration The length of the animation, in milliseconds, of each of the child 328a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * animations of this AnimatorSet. 32921cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 33021cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 3312794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public AnimatorSet setDuration(long duration) { 33221cd1389d2ef218b20994b617c57af120841a57fChet Haase if (duration < 0) { 33321cd1389d2ef218b20994b617c57af120841a57fChet Haase throw new IllegalArgumentException("duration must be a value of zero or greater"); 33421cd1389d2ef218b20994b617c57af120841a57fChet Haase } 33521cd1389d2ef218b20994b617c57af120841a57fChet Haase for (Node node : mNodes) { 336a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // TODO: don't set the duration of the timing-only nodes created by AnimatorSet to 33721cd1389d2ef218b20994b617c57af120841a57fChet Haase // insert "play-after" delays 33821cd1389d2ef218b20994b617c57af120841a57fChet Haase node.animation.setDuration(duration); 33921cd1389d2ef218b20994b617c57af120841a57fChet Haase } 34021cd1389d2ef218b20994b617c57af120841a57fChet Haase mDuration = duration; 3412794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase return this; 34221cd1389d2ef218b20994b617c57af120841a57fChet Haase } 34321cd1389d2ef218b20994b617c57af120841a57fChet Haase 34421cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 34517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * {@inheritDoc} 34617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 347a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>Starting this <code>AnimatorSet</code> will, in turn, start the animations for which 34817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * it is responsible. The details of when exactly those animations are started depends on 34917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * the dependency relationships that have been set up between the animations. 35017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 35117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @SuppressWarnings("unchecked") 35217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @Override 35317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public void start() { 354010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase mCanceled = false; 355010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase 35617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // First, sort the nodes (if necessary). This will ensure that sortedNodes 35717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // contains the animation nodes in the correct order. 35817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase sortNodes(); 35917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 36017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // nodesToStart holds the list of nodes to be started immediately. We don't want to 36117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // start the animations in the loop directly because we first need to set up 36217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // dependencies on all of the nodes. For example, we don't want to start an animation 36317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // when some other animation also wants to start when the first animation begins. 36421cd1389d2ef218b20994b617c57af120841a57fChet Haase final ArrayList<Node> nodesToStart = new ArrayList<Node>(); 3657c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numSortedNodes = mSortedNodes.size(); 3667c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numSortedNodes; ++i) { 3677c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Node node = mSortedNodes.get(i); 368a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (mSetListener == null) { 369a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase mSetListener = new AnimatorSetListener(this); 37017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 37117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node.dependencies == null || node.dependencies.size() == 0) { 37217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase nodesToStart.add(node); 37317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } else { 3747c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numDependencies = node.dependencies.size(); 3757c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int j = 0; j < numDependencies; ++j) { 3767c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Dependency dependency = node.dependencies.get(j); 37717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependency.node.animation.addListener( 378010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase new DependencyListener(this, node, dependency.rule)); 37917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 38017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.tmpDependencies = (ArrayList<Dependency>) node.dependencies.clone(); 38117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 382a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase node.animation.addListener(mSetListener); 38317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 38417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // Now that all dependencies are set up, start the animations that should be started. 38521cd1389d2ef218b20994b617c57af120841a57fChet Haase if (mStartDelay <= 0) { 38621cd1389d2ef218b20994b617c57af120841a57fChet Haase for (Node node : nodesToStart) { 38721cd1389d2ef218b20994b617c57af120841a57fChet Haase node.animation.start(); 38821cd1389d2ef218b20994b617c57af120841a57fChet Haase mPlayingSet.add(node.animation); 38921cd1389d2ef218b20994b617c57af120841a57fChet Haase } 39021cd1389d2ef218b20994b617c57af120841a57fChet Haase } else { 39121cd1389d2ef218b20994b617c57af120841a57fChet Haase // TODO: Need to cancel out of the delay appropriately 3922794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase ValueAnimator delayAnim = ValueAnimator.ofFloat(0f, 1f); 3932794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase delayAnim.setDuration(mStartDelay); 394a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase delayAnim.addListener(new AnimatorListenerAdapter() { 395a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationEnd(Animator anim) { 3967c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numNodes = nodesToStart.size(); 3977c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numNodes; ++i) { 3987c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Node node = nodesToStart.get(i); 39921cd1389d2ef218b20994b617c57af120841a57fChet Haase node.animation.start(); 40021cd1389d2ef218b20994b617c57af120841a57fChet Haase mPlayingSet.add(node.animation); 40121cd1389d2ef218b20994b617c57af120841a57fChet Haase } 40221cd1389d2ef218b20994b617c57af120841a57fChet Haase } 40321cd1389d2ef218b20994b617c57af120841a57fChet Haase }); 40417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 40517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mListeners != null) { 406a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ArrayList<AnimatorListener> tmpListeners = 407a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase (ArrayList<AnimatorListener>) mListeners.clone(); 4087c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numListeners = tmpListeners.size(); 4097c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numListeners; ++i) { 4107c608f25d494c8a0a671e7373efbb47ca635367eChet Haase tmpListeners.get(i).onAnimationStart(this); 41117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 41217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 41317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 41417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 41549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase @Override 416a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public AnimatorSet clone() { 417a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase final AnimatorSet anim = (AnimatorSet) super.clone(); 41849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase /* 41949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * The basic clone() operation copies all items. This doesn't work very well for 420a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet, because it will copy references that need to be recreated and state 42149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * that may not apply. What we need to do now is put the clone in an uninitialized 42249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * state, with fresh, empty data structures. Then we will build up the nodes list 42349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * manually, as we clone each Node (and its animation). The clone will then be sorted, 42449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * and will populate any appropriate lists, when it is started. 42549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase */ 42649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase anim.mNeedsSort = true; 42749afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase anim.mCanceled = false; 428a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase anim.mPlayingSet = new ArrayList<Animator>(); 429a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase anim.mNodeMap = new HashMap<Animator, Node>(); 43049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase anim.mNodes = new ArrayList<Node>(); 43149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase anim.mSortedNodes = new ArrayList<Node>(); 43249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase 43349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // Walk through the old nodes list, cloning each node and adding it to the new nodemap. 434a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // One problem is that the old node dependencies point to nodes in the old AnimatorSet. 43549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // We need to track the old/new nodes in order to reconstruct the dependencies in the clone. 43649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase HashMap<Node, Node> nodeCloneMap = new HashMap<Node, Node>(); // <old, new> 43749afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase for (Node node : mNodes) { 43849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase Node nodeClone = node.clone(); 43949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase nodeCloneMap.put(node, nodeClone); 44049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase anim.mNodes.add(nodeClone); 44149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase anim.mNodeMap.put(nodeClone.animation, nodeClone); 44249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // Clear out the dependencies in the clone; we'll set these up manually later 44349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase nodeClone.dependencies = null; 44449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase nodeClone.tmpDependencies = null; 44549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase nodeClone.nodeDependents = null; 44649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase nodeClone.nodeDependencies = null; 447a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // clear out any listeners that were set up by the AnimatorSet; these will 44849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // be set up when the clone's nodes are sorted 449a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ArrayList<AnimatorListener> cloneListeners = nodeClone.animation.getListeners(); 45049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase if (cloneListeners != null) { 451a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ArrayList<AnimatorListener> listenersToRemove = null; 452a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase for (AnimatorListener listener : cloneListeners) { 453a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (listener instanceof AnimatorSetListener) { 45449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase if (listenersToRemove == null) { 455a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase listenersToRemove = new ArrayList<AnimatorListener>(); 45649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 45749afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase listenersToRemove.add(listener); 45849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 45949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 46049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase if (listenersToRemove != null) { 461a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase for (AnimatorListener listener : listenersToRemove) { 46249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase cloneListeners.remove(listener); 46349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 46449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 46549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 46649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 46749afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // Now that we've cloned all of the nodes, we're ready to walk through their 46849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // dependencies, mapping the old dependencies to the new nodes 46949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase for (Node node : mNodes) { 47049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase Node nodeClone = nodeCloneMap.get(node); 47149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase if (node.dependencies != null) { 47249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase for (Dependency dependency : node.dependencies) { 47349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase Node clonedDependencyNode = nodeCloneMap.get(dependency.node); 47449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase Dependency cloneDependency = new Dependency(clonedDependencyNode, 47549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase dependency.rule); 47649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase nodeClone.addDependency(cloneDependency); 47749afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 47849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 47949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 48049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase 48149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase return anim; 48249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 48349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase 48417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 48517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * This class is the mechanism by which animations are started based on events in other 48617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * animations. If an animation has multiple dependencies on other animations, then 48717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * all dependencies must be satisfied before the animation is started. 48817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 489a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private static class DependencyListener implements AnimatorListener { 49017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 491a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private AnimatorSet mAnimatorSet; 492010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase 49317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // The node upon which the dependency is based. 49417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private Node mNode; 49517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 49617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // The Dependency rule (WITH or AFTER) that the listener should wait for on 49717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // the node 49817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private int mRule; 49917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 500a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public DependencyListener(AnimatorSet animatorSet, Node node, int rule) { 501a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase this.mAnimatorSet = animatorSet; 50217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase this.mNode = node; 50317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase this.mRule = rule; 50417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 50517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 50617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 507010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase * Ignore cancel events for now. We may want to handle this eventually, 508010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase * to prevent follow-on animations from running when some dependency 509010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase * animation is canceled. 51017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 511a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationCancel(Animator animation) { 51217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 51317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 51417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 51517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * An end event is received - see if this is an event we are listening for 51617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 517a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationEnd(Animator animation) { 51817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mRule == Dependency.AFTER) { 51917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase startIfReady(animation); 52017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 52117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 52217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 52317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 52417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Ignore repeat events for now 52517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 526a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationRepeat(Animator animation) { 52717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 52817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 52917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 53017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * A start event is received - see if this is an event we are listening for 53117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 532a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationStart(Animator animation) { 53317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mRule == Dependency.WITH) { 53417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase startIfReady(animation); 53517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 53617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 53717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 53817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 53917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Check whether the event received is one that the node was waiting for. 54017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * If so, mark it as complete and see whether it's time to start 54117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * the animation. 54217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param dependencyAnimation the animation that sent the event. 54317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 544a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private void startIfReady(Animator dependencyAnimation) { 545a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (mAnimatorSet.mCanceled) { 546a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // if the parent AnimatorSet was canceled, then don't start any dependent anims 547010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase return; 548010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase } 54917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Dependency dependencyToRemove = null; 5507c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numDependencies = mNode.tmpDependencies.size(); 5517c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numDependencies; ++i) { 5527c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Dependency dependency = mNode.tmpDependencies.get(i); 55317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (dependency.rule == mRule && 55417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependency.node.animation == dependencyAnimation) { 55517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // rule fired - remove the dependency and listener and check to 55617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // see whether it's time to start the animation 55717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencyToRemove = dependency; 55817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencyAnimation.removeListener(this); 55917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase break; 56017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 56117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 56217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNode.tmpDependencies.remove(dependencyToRemove); 56317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mNode.tmpDependencies.size() == 0) { 56417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // all dependencies satisfied: start the animation 56517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNode.animation.start(); 566a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase mAnimatorSet.mPlayingSet.add(mNode.animation); 56717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 56817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 56917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 57017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 57117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 572a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private class AnimatorSetListener implements AnimatorListener { 57317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 574a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private AnimatorSet mAnimatorSet; 57517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 576a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase AnimatorSetListener(AnimatorSet animatorSet) { 577a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase mAnimatorSet = animatorSet; 57817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 57917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 580a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationCancel(Animator animation) { 58117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mPlayingSet.size() == 0) { 58217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mListeners != null) { 5837c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numListeners = mListeners.size(); 5847c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numListeners; ++i) { 5857c608f25d494c8a0a671e7373efbb47ca635367eChet Haase mListeners.get(i).onAnimationCancel(mAnimatorSet); 58617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 58717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 58817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 58917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 59017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 59117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @SuppressWarnings("unchecked") 592a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationEnd(Animator animation) { 59317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase animation.removeListener(this); 59417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mPlayingSet.remove(animation); 595a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase Node animNode = mAnimatorSet.mNodeMap.get(animation); 5961e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase animNode.done = true; 597a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ArrayList<Node> sortedNodes = mAnimatorSet.mSortedNodes; 598a6e4a1757728efc91627ece602b0899d75303659Chet Haase boolean allDone = true; 5997c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numSortedNodes = sortedNodes.size(); 6007c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numSortedNodes; ++i) { 6017c608f25d494c8a0a671e7373efbb47ca635367eChet Haase if (!sortedNodes.get(i).done) { 602a6e4a1757728efc91627ece602b0899d75303659Chet Haase allDone = false; 603a6e4a1757728efc91627ece602b0899d75303659Chet Haase break; 604a6e4a1757728efc91627ece602b0899d75303659Chet Haase } 605a6e4a1757728efc91627ece602b0899d75303659Chet Haase } 606a6e4a1757728efc91627ece602b0899d75303659Chet Haase if (allDone) { 60717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // If this was the last child animation to end, then notify listeners that this 608a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // AnimatorSet has ended 60917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mListeners != null) { 610a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ArrayList<AnimatorListener> tmpListeners = 611a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase (ArrayList<AnimatorListener>) mListeners.clone(); 6127c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numListeners = tmpListeners.size(); 6137c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numListeners; ++i) { 6147c608f25d494c8a0a671e7373efbb47ca635367eChet Haase tmpListeners.get(i).onAnimationEnd(mAnimatorSet); 61517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 61617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 61717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 61817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 61917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 62017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // Nothing to do 621a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationRepeat(Animator animation) { 62217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 62317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 62417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // Nothing to do 625a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationStart(Animator animation) { 62617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 62717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 62817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 62917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 63017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 63117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * This method sorts the current set of nodes, if needed. The sort is a simple 63217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * DependencyGraph sort, which goes like this: 63317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - All nodes without dependencies become 'roots' 63417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - while roots list is not null 63517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - for each root r 63617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - add r to sorted list 63717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - remove r as a dependency from any other node 63817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - any nodes with no dependencies are added to the roots list 63917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 64017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private void sortNodes() { 64117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mNeedsSort) { 64217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mSortedNodes.clear(); 64317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase ArrayList<Node> roots = new ArrayList<Node>(); 6447c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numNodes = mNodes.size(); 6457c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numNodes; ++i) { 6467c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Node node = mNodes.get(i); 64717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node.dependencies == null || node.dependencies.size() == 0) { 64817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase roots.add(node); 64917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 65017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 65117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase ArrayList<Node> tmpRoots = new ArrayList<Node>(); 65217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase while (roots.size() > 0) { 6537c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numRoots = roots.size(); 6547c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numRoots; ++i) { 6557c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Node root = roots.get(i); 65617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mSortedNodes.add(root); 65717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (root.nodeDependents != null) { 6587c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numDependents = root.nodeDependents.size(); 6597c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int j = 0; j < numDependents; ++j) { 6607c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Node node = root.nodeDependents.get(j); 66117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.nodeDependencies.remove(root); 66217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node.nodeDependencies.size() == 0) { 66317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase tmpRoots.add(node); 66417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 66517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 66617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 66717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 668010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase roots.clear(); 66917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase roots.addAll(tmpRoots); 67017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase tmpRoots.clear(); 67117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 67217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNeedsSort = false; 67317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mSortedNodes.size() != mNodes.size()) { 67417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase throw new IllegalStateException("Circular dependencies cannot exist" 675a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase + " in AnimatorSet"); 67617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 67717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } else { 67817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // Doesn't need sorting, but still need to add in the nodeDependencies list 67917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // because these get removed as the event listeners fire and the dependencies 68017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // are satisfied 6817c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numNodes = mNodes.size(); 6827c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numNodes; ++i) { 6837c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Node node = mNodes.get(i); 68417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node.dependencies != null && node.dependencies.size() > 0) { 6857c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numDependencies = node.dependencies.size(); 6867c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int j = 0; j < numDependencies; ++j) { 6877c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Dependency dependency = node.dependencies.get(j); 68817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node.nodeDependencies == null) { 68917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.nodeDependencies = new ArrayList<Node>(); 69017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 69117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (!node.nodeDependencies.contains(dependency.node)) { 69217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.nodeDependencies.add(dependency.node); 69317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 69417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 69517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 6961e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase node.done = false; 69717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 69817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 69917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 70017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 70117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 70217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Dependency holds information about the node that some other node is 70317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * dependent upon and the nature of that dependency. 70417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 70517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 70617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private static class Dependency { 70717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase static final int WITH = 0; // dependent node must start with this dependency node 70817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase static final int AFTER = 1; // dependent node must start when this dependency node finishes 70917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 71017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // The node that the other node with this Dependency is dependent upon 71117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public Node node; 71217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 71317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // The nature of the dependency (WITH or AFTER) 71417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public int rule; 71517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 71617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public Dependency(Node node, int rule) { 71717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase this.node = node; 71817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase this.rule = rule; 71917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 72017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 72117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 72217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 723a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * A Node is an embodiment of both the Animator that it wraps as well as 72417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * any dependencies that are associated with that Animation. This includes 72517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * both dependencies upon other nodes (in the dependencies list) as 72617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * well as dependencies of other nodes upon this (in the nodeDependents list). 72717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 72849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase private static class Node implements Cloneable { 729a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public Animator animation; 73017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 73117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 73217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * These are the dependencies that this node's animation has on other 73317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * nodes. For example, if this node's animation should begin with some 73417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * other animation ends, then there will be an item in this node's 73517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * dependencies list for that other animation's node. 73617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 73717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public ArrayList<Dependency> dependencies = null; 73817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 73917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 74017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * tmpDependencies is a runtime detail. We use the dependencies list for sorting. 74117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * But we also use the list to keep track of when multiple dependencies are satisfied, 74217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * but removing each dependency as it is satisfied. We do not want to remove 74317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * the dependency itself from the list, because we need to retain that information 744a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * if the AnimatorSet is launched in the future. So we create a copy of the dependency 745a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * list when the AnimatorSet starts and use this tmpDependencies list to track the 74617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * list of satisfied dependencies. 74717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 74817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public ArrayList<Dependency> tmpDependencies = null; 74917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 75017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 75117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * nodeDependencies is just a list of the nodes that this Node is dependent upon. 75217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * This information is used in sortNodes(), to determine when a node is a root. 75317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 75417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public ArrayList<Node> nodeDependencies = null; 75517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 75617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 75717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * nodeDepdendents is the list of nodes that have this node as a dependency. This 75817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * is a utility field used in sortNodes to facilitate removing this node as a 75917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * dependency when it is a root node. 76017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 76117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public ArrayList<Node> nodeDependents = null; 76217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 76317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 7641e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase * Flag indicating whether the animation in this node is finished. This flag 765a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * is used by AnimatorSet to check, as each animation ends, whether all child animations 766a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * are done and it's time to send out an end event for the entire AnimatorSet. 7671e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase */ 7681e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase public boolean done = false; 7691e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase 7701e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase /** 77117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Constructs the Node with the animation that it encapsulates. A Node has no 77217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * dependencies by default; dependencies are added via the addDependency() 77317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * method. 77417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 77517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param animation The animation that the Node encapsulates. 77617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 777a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public Node(Animator animation) { 77817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase this.animation = animation; 77917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 78017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 78117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 78217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Add a dependency to this Node. The dependency includes information about the 78317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * node that this node is dependency upon and the nature of the dependency. 78417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param dependency 78517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 78617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public void addDependency(Dependency dependency) { 78717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (dependencies == null) { 78817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencies = new ArrayList<Dependency>(); 78917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase nodeDependencies = new ArrayList<Node>(); 79017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 79117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencies.add(dependency); 79217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (!nodeDependencies.contains(dependency.node)) { 79317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase nodeDependencies.add(dependency.node); 79417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 79517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Node dependencyNode = dependency.node; 79617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (dependencyNode.nodeDependents == null) { 79717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencyNode.nodeDependents = new ArrayList<Node>(); 79817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 79917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencyNode.nodeDependents.add(this); 80017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 80149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase 80249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase @Override 80321cd1389d2ef218b20994b617c57af120841a57fChet Haase public Node clone() { 80421cd1389d2ef218b20994b617c57af120841a57fChet Haase try { 80521cd1389d2ef218b20994b617c57af120841a57fChet Haase Node node = (Node) super.clone(); 806a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase node.animation = (Animator) animation.clone(); 80721cd1389d2ef218b20994b617c57af120841a57fChet Haase return node; 80821cd1389d2ef218b20994b617c57af120841a57fChet Haase } catch (CloneNotSupportedException e) { 80921cd1389d2ef218b20994b617c57af120841a57fChet Haase throw new AssertionError(); 81021cd1389d2ef218b20994b617c57af120841a57fChet Haase } 81149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 81217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 81317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 81417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 81517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * The <code>Builder</code> object is a utility class to facilitate adding animations to a 816a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <code>AnimatorSet</code> along with the relationships between the various animations. The 81717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * intention of the <code>Builder</code> methods, along with the {@link 818a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet#play(Animator) play()} method of <code>AnimatorSet</code> is to make it possible to 81917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * express the dependency relationships of animations in a natural way. Developers can also use 820a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * the {@link AnimatorSet#playTogether(Animator[]) playTogether()} and {@link 821a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet#playSequentially(Animator[]) playSequentially()} methods if these suit the need, 822a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * but it might be easier in some situations to express the AnimatorSet of animations in pairs. 82317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p/> 82417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p>The <code>Builder</code> object cannot be constructed directly, but is rather constructed 825a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * internally via a call to {@link AnimatorSet#play(Animator)}.</p> 82617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p/> 827a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>For example, this sets up a AnimatorSet to play anim1 and anim2 at the same time, anim3 to 82817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * play when anim2 finishes, and anim4 to play when anim3 finishes:</p> 82917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <pre> 830a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet s = new AnimatorSet(); 83117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim1).with(anim2); 83217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim2).before(anim3); 83317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim4).after(anim3); 83417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * </pre> 83517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p/> 836a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>Note in the example that both {@link Builder#before(Animator)} and {@link 837a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Builder#after(Animator)} are used. These are just different ways of expressing the same 83817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * relationship and are provided to make it easier to say things in a way that is more natural, 83917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * depending on the situation.</p> 84017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p/> 84117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p>It is possible to make several calls into the same <code>Builder</code> object to express 84217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * multiple relationships. However, note that it is only the animation passed into the initial 843a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} method that is the dependency in any of the successive 84417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * calls to the <code>Builder</code> object. For example, the following code starts both anim2 84517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * and anim3 when anim1 ends; there is no direct dependency relationship between anim2 and 84617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * anim3: 84717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <pre> 848a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet s = new AnimatorSet(); 84917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim1).before(anim2).before(anim3); 85017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * </pre> 85117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * If the desired result is to play anim1 then anim2 then anim3, this code expresses the 85217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * relationship correctly:</p> 85317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <pre> 854a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet s = new AnimatorSet(); 85517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim1).before(anim2); 85617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim2).before(anim3); 85717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * </pre> 85817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p/> 85917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p>Note that it is possible to express relationships that cannot be resolved and will not 86017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * result in sensible results. For example, <code>play(anim1).after(anim1)</code> makes no 86117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * sense. In general, circular dependencies like this one (or more indirect ones where a depends 862a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * on b, which depends on c, which depends on a) should be avoided. Only create AnimatorSets 863a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * that can boil down to a simple, one-way relationship of animations starting with, before, and 86417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * after other, different, animations.</p> 86517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 86617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public class Builder { 86717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 86817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 86917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * This tracks the current node being processed. It is supplied to the play() method 870a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * of AnimatorSet and passed into the constructor of Builder. 87117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 87217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private Node mCurrentNode; 87317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 87417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 875a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * package-private constructor. Builders are only constructed by AnimatorSet, when the 87617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * play() method is called. 87717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 87817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param anim The animation that is the dependency for the other animations passed into 87917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * the other methods of this Builder object. 88017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 881a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase Builder(Animator anim) { 88217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mCurrentNode = mNodeMap.get(anim); 88317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mCurrentNode == null) { 88417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mCurrentNode = new Node(anim); 88517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodeMap.put(anim, mCurrentNode); 88617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodes.add(mCurrentNode); 88717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 88817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 88917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 89017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 89117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Sets up the given animation to play at the same time as the animation supplied in the 892a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object. 89317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 89417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param anim The animation that will play when the animation supplied to the 895a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} method starts. 89617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 897a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void with(Animator anim) { 89817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Node node = mNodeMap.get(anim); 89917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node == null) { 90017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node = new Node(anim); 90117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodeMap.put(anim, node); 90217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodes.add(node); 90317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 90417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Dependency dependency = new Dependency(mCurrentNode, Dependency.WITH); 90517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.addDependency(dependency); 90617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 90717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 90817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 90917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Sets up the given animation to play when the animation supplied in the 910a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object 91117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * ends. 91217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 91317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param anim The animation that will play when the animation supplied to the 914a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} method ends. 91517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 916a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void before(Animator anim) { 91717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Node node = mNodeMap.get(anim); 91817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node == null) { 91917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node = new Node(anim); 92017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodeMap.put(anim, node); 92117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodes.add(node); 92217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 92317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Dependency dependency = new Dependency(mCurrentNode, Dependency.AFTER); 92417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.addDependency(dependency); 92517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 92617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 92717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 92817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Sets up the given animation to play when the animation supplied in the 929a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object 93017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * to start when the animation supplied in this method call ends. 93117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 93217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param anim The animation whose end will cause the animation supplied to the 933a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} method to play. 93417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 935a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void after(Animator anim) { 93617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Node node = mNodeMap.get(anim); 93717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node == null) { 93817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node = new Node(anim); 93917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodeMap.put(anim, node); 94017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodes.add(node); 94117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 94217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Dependency dependency = new Dependency(node, Dependency.AFTER); 94317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mCurrentNode.addDependency(dependency); 94417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 94517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 94617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 94717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Sets up the animation supplied in the 948a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object 94917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * to play when the given amount of time elapses. 95017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 95117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param delay The number of milliseconds that should elapse before the 95217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * animation starts. 95317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 95417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public void after(long delay) { 955a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // setup dummy ValueAnimator just to run the clock 9562794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); 9572794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase anim.setDuration(delay); 9582794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase after(anim); 95917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 96017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 96117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 96217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 96317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase} 964