AnimatorSet.java revision d7444427d9f44b6b7448d4c21edca866132c8b59
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 19d7444427d9f44b6b7448d4c21edca866132c8b59Doris Liuimport android.util.ArrayMap; 20d7444427d9f44b6b7448d4c21edca866132c8b59Doris Liu 2117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haaseimport java.util.ArrayList; 2237a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haaseimport java.util.Collection; 2337a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haaseimport java.util.List; 2417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 2517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase/** 26a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * This class plays a set of {@link Animator} objects in the specified order. Animations 2717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * can be set up to play together, in sequence, or after a specified delay. 2817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 29a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>There are two different approaches to adding animations to a <code>AnimatorSet</code>: 30a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * either the {@link AnimatorSet#playTogether(Animator[]) playTogether()} or 31a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#playSequentially(Animator[]) playSequentially()} methods can be called to add 32a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * a set of animations all at once, or the {@link AnimatorSet#play(Animator)} can be 33a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * used in conjunction with methods in the {@link AnimatorSet.Builder Builder} 3417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * class to add animations 3517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * one by one.</p> 3617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 37a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>It is possible to set up a <code>AnimatorSet</code> with circular dependencies between 3817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * its animations. For example, an animation a1 could be set up to start before animation a2, a2 3917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * before a3, and a3 before a1. The results of this configuration are undefined, but will typically 4017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * result in none of the affected animations being played. Because of this (and because 4117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * circular dependencies do not make logical sense anyway), circular dependencies 4217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * should be avoided, and the dependency flow of animations should only be in one direction. 433aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * 443aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <div class="special reference"> 453aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <h3>Developer Guides</h3> 463aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <p>For more information about animating with {@code AnimatorSet}, read the 473aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <a href="{@docRoot}guide/topics/graphics/prop-animation.html#choreography">Property 483aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * Animation</a> developer guide.</p> 493aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * </div> 5017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 51a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haasepublic final class AnimatorSet extends Animator { 5217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 5317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 5449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * Internal variables 5549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * NOTE: This object implements the clone() method, making a deep copy of any referenced 5649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * objects. As other non-trivial fields are added to this class, make sure to add logic 5749afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * to clone() to make deep copies of them. 5849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase */ 5949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase 6049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase /** 613b69b6f0be85d1f97c1e6824cf986777ba4e5d00Chet Haase * Tracks animations currently being played, so that we know what to 62a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * cancel or end when cancel() or end() is called on this AnimatorSet 6317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 64a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private ArrayList<Animator> mPlayingSet = new ArrayList<Animator>(); 6517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 6617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 67a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Contains all nodes, mapped to their respective Animators. When new 68a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * dependency information is added for an Animator, we want to add it 69a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * to a single node representing that Animator, not create a new Node 7017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * if one already exists. 7117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 72d7444427d9f44b6b7448d4c21edca866132c8b59Doris Liu private ArrayMap<Animator, Node> mNodeMap = new ArrayMap<Animator, Node>(); 7317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 7417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 75a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Set of all nodes created for this AnimatorSet. This list is used upon 76a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * starting the set, and the nodes are placed in sorted order into the 7717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * sortedNodes collection. 7817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 7949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase private ArrayList<Node> mNodes = new ArrayList<Node>(); 8017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 8117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 8217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * The sorted list of nodes. This is the order in which the animations will 8317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * be played. The details about when exactly they will be played depend 8417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * on the dependency relationships of the nodes. 8517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 8649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase private ArrayList<Node> mSortedNodes = new ArrayList<Node>(); 8717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 8817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 8917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Flag indicating whether the nodes should be sorted prior to playing. This 9017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * flag allows us to cache the previous sorted nodes so that if the sequence 9117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * is replayed with no changes, it does not have to re-sort the nodes again. 9217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 9317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private boolean mNeedsSort = true; 9417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 95a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private AnimatorSetListener mSetListener = null; 9617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 9717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 987dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase * Flag indicating that the AnimatorSet has been manually 997dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase * terminated (by calling cancel() or end()). 100010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase * This flag is used to avoid starting other animations when currently-playing 1017dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase * child animations of this AnimatorSet end. It also determines whether cancel/end 1027dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase * notifications are sent out via the normal AnimatorSetListener mechanism. 103010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase */ 1047dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase boolean mTerminated = false; 105010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase 1068b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase /** 1078b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase * Indicates whether an AnimatorSet has been start()'d, whether or 1088b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase * not there is a nonzero startDelay. 1098b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase */ 1108b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase private boolean mStarted = false; 1118b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase 11221cd1389d2ef218b20994b617c57af120841a57fChet Haase // The amount of time in ms to delay starting the animation after start() is called 11321cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mStartDelay = 0; 11421cd1389d2ef218b20994b617c57af120841a57fChet Haase 115e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase // Animator used for a nonzero startDelay 116e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase private ValueAnimator mDelayAnim = null; 117e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase 11821cd1389d2ef218b20994b617c57af120841a57fChet Haase 11921cd1389d2ef218b20994b617c57af120841a57fChet Haase // How long the child animations should last in ms. The default value is negative, which 120a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // simply means that there is no duration set on the AnimatorSet. When a real duration is 12121cd1389d2ef218b20994b617c57af120841a57fChet Haase // set, it is passed along to the child animations. 12221cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mDuration = -1; 12321cd1389d2ef218b20994b617c57af120841a57fChet Haase 124430742f09063574271e6c4091de13b9b9e762514Chet Haase // Records the interpolator for the set. Null value indicates that no interpolator 125430742f09063574271e6c4091de13b9b9e762514Chet Haase // was set on this AnimatorSet, so it should not be passed down to the children. 126430742f09063574271e6c4091de13b9b9e762514Chet Haase private TimeInterpolator mInterpolator = null; 127430742f09063574271e6c4091de13b9b9e762514Chet Haase 1287bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui private boolean mReversible = true; 129010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase /** 130a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Sets up this AnimatorSet to play all of the supplied animations at the same time. 131430742f09063574271e6c4091de13b9b9e762514Chet Haase * This is equivalent to calling {@link #play(Animator)} with the first animator in the 132430742f09063574271e6c4091de13b9b9e762514Chet Haase * set and then {@link Builder#with(Animator)} with each of the other animators. Note that 133430742f09063574271e6c4091de13b9b9e762514Chet Haase * an Animator with a {@link Animator#setStartDelay(long) startDelay} will not actually 134430742f09063574271e6c4091de13b9b9e762514Chet Haase * start until that delay elapses, which means that if the first animator in the list 135430742f09063574271e6c4091de13b9b9e762514Chet Haase * supplied to this constructor has a startDelay, none of the other animators will start 136430742f09063574271e6c4091de13b9b9e762514Chet Haase * until that first animator's startDelay has elapsed. 13717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 138a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @param items The animations that will be started simultaneously. 13917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 140a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void playTogether(Animator... items) { 141a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (items != null) { 14217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNeedsSort = true; 143a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase Builder builder = play(items[0]); 144a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase for (int i = 1; i < items.length; ++i) { 145a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase builder.with(items[i]); 14617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 14717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 14817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 14917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 15017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 15137a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase * Sets up this AnimatorSet to play all of the supplied animations at the same time. 15237a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase * 15337a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase * @param items The animations that will be started simultaneously. 15437a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase */ 15537a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase public void playTogether(Collection<Animator> items) { 15637a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase if (items != null && items.size() > 0) { 15737a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase mNeedsSort = true; 15837a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase Builder builder = null; 15937a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase for (Animator anim : items) { 16037a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase if (builder == null) { 16137a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase builder = play(anim); 16237a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase } else { 16337a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase builder.with(anim); 16437a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase } 16537a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase } 16637a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase } 16737a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase } 16837a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase 16937a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase /** 170a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Sets up this AnimatorSet to play each of the supplied animations when the 17117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * previous animation ends. 17217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 17337a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase * @param items The animations that will be started one after another. 17417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 175a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void playSequentially(Animator... items) { 176a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (items != null) { 17717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNeedsSort = true; 178a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (items.length == 1) { 179a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase play(items[0]); 18017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } else { 1817bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui mReversible = false; 182a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase for (int i = 0; i < items.length - 1; ++i) { 183a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase play(items[i]).before(items[i+1]); 18417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 18517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 18617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 18717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 18817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 18917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 19037a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase * Sets up this AnimatorSet to play each of the supplied animations when the 19137a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase * previous animation ends. 19237a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase * 19337a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase * @param items The animations that will be started one after another. 19437a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase */ 19537a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase public void playSequentially(List<Animator> items) { 19637a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase if (items != null && items.size() > 0) { 19737a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase mNeedsSort = true; 19837a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase if (items.size() == 1) { 19937a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase play(items.get(0)); 20037a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase } else { 2017bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui mReversible = false; 20237a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase for (int i = 0; i < items.size() - 1; ++i) { 20337a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase play(items.get(i)).before(items.get(i+1)); 20437a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase } 20537a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase } 20637a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase } 20737a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase } 20837a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase 20937a7bec599e8d877d8a7f12ab2c2c160d1c2cf8aChet Haase /** 210a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Returns the current list of child Animator objects controlled by this 211a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet. This is a copy of the internal list; modifications to the returned list 212a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * will not affect the AnimatorSet, although changes to the underlying Animator objects 213a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * will affect those objects being managed by the AnimatorSet. 214f54a8d7c479485174941c38f151ea7083c658da3Chet Haase * 215a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @return ArrayList<Animator> The list of child animations of this AnimatorSet. 216f54a8d7c479485174941c38f151ea7083c658da3Chet Haase */ 217a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public ArrayList<Animator> getChildAnimations() { 218a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ArrayList<Animator> childList = new ArrayList<Animator>(); 219f54a8d7c479485174941c38f151ea7083c658da3Chet Haase for (Node node : mNodes) { 220f54a8d7c479485174941c38f151ea7083c658da3Chet Haase childList.add(node.animation); 221f54a8d7c479485174941c38f151ea7083c658da3Chet Haase } 222f54a8d7c479485174941c38f151ea7083c658da3Chet Haase return childList; 223f54a8d7c479485174941c38f151ea7083c658da3Chet Haase } 224f54a8d7c479485174941c38f151ea7083c658da3Chet Haase 225f54a8d7c479485174941c38f151ea7083c658da3Chet Haase /** 226811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase * Sets the target object for all current {@link #getChildAnimations() child animations} 227a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * of this AnimatorSet that take targets ({@link ObjectAnimator} and 228a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet). 229811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase * 230811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase * @param target The object being animated 231811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase */ 23221cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 233811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase public void setTarget(Object target) { 234811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase for (Node node : mNodes) { 235a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase Animator animation = node.animation; 236a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (animation instanceof AnimatorSet) { 237a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ((AnimatorSet)animation).setTarget(target); 238a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase } else if (animation instanceof ObjectAnimator) { 239a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ((ObjectAnimator)animation).setTarget(target); 240811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase } 241811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase } 242811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase } 243811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase 244811ed1065f39469cf2cf6adba22cab397ed88d5eChet Haase /** 245d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar * @hide 246d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar */ 247d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar @Override 248d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar public int getChangingConfigurations() { 249d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar int conf = super.getChangingConfigurations(); 250d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar final int nodeCount = mNodes.size(); 251d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar for (int i = 0; i < nodeCount; i ++) { 252d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar conf |= mNodes.get(i).animation.getChangingConfigurations(); 253d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar } 254d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar return conf; 255d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar } 256d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar 257d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar /** 258e0ee2e9f3102c3c14c873a75a7b04e49787e0fb9Chet Haase * Sets the TimeInterpolator for all current {@link #getChildAnimations() child animations} 259430742f09063574271e6c4091de13b9b9e762514Chet Haase * of this AnimatorSet. The default value is null, which means that no interpolator 260430742f09063574271e6c4091de13b9b9e762514Chet Haase * is set on this AnimatorSet. Setting the interpolator to any non-null value 261430742f09063574271e6c4091de13b9b9e762514Chet Haase * will cause that interpolator to be set on the child animations 262430742f09063574271e6c4091de13b9b9e762514Chet Haase * when the set is started. 26321cd1389d2ef218b20994b617c57af120841a57fChet Haase * 264a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @param interpolator the interpolator to be used by each child animation of this AnimatorSet 26521cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 26621cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 267e0ee2e9f3102c3c14c873a75a7b04e49787e0fb9Chet Haase public void setInterpolator(TimeInterpolator interpolator) { 268430742f09063574271e6c4091de13b9b9e762514Chet Haase mInterpolator = interpolator; 269430742f09063574271e6c4091de13b9b9e762514Chet Haase } 270430742f09063574271e6c4091de13b9b9e762514Chet Haase 271430742f09063574271e6c4091de13b9b9e762514Chet Haase @Override 272430742f09063574271e6c4091de13b9b9e762514Chet Haase public TimeInterpolator getInterpolator() { 273430742f09063574271e6c4091de13b9b9e762514Chet Haase return mInterpolator; 27421cd1389d2ef218b20994b617c57af120841a57fChet Haase } 27521cd1389d2ef218b20994b617c57af120841a57fChet Haase 27621cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 27717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * This method creates a <code>Builder</code> object, which is used to 27817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * set up playing constraints. This initial <code>play()</code> method 27917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * tells the <code>Builder</code> the animation that is the dependency for 28017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * the succeeding commands to the <code>Builder</code>. For example, 281a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * calling <code>play(a1).with(a2)</code> sets up the AnimatorSet to play 28217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>a1</code> and <code>a2</code> at the same time, 283a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <code>play(a1).before(a2)</code> sets up the AnimatorSet to play 28417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>a1</code> first, followed by <code>a2</code>, and 285a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <code>play(a1).after(a2)</code> sets up the AnimatorSet to play 28617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>a2</code> first, followed by <code>a1</code>. 28717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 28817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p>Note that <code>play()</code> is the only way to tell the 28917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>Builder</code> the animation upon which the dependency is created, 29017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * so successive calls to the various functions in <code>Builder</code> 29117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * will all refer to the initial parameter supplied in <code>play()</code> 29217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * as the dependency of the other animations. For example, calling 29317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>play(a1).before(a2).before(a3)</code> will play both <code>a2</code> 29417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * and <code>a3</code> when a1 ends; it does not set up a dependency between 29517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>a2</code> and <code>a3</code>.</p> 29617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 29717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param anim The animation that is the dependency used in later calls to the 29817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * methods in the returned <code>Builder</code> object. A null parameter will result 29917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * in a null <code>Builder</code> return value. 300a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @return Builder The object that constructs the AnimatorSet based on the dependencies 30117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * outlined in the calls to <code>play</code> and the other methods in the 30217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <code>Builder</code object. 30317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 304a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public Builder play(Animator anim) { 30517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (anim != null) { 30617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNeedsSort = true; 30717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase return new Builder(anim); 30817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 30917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase return null; 31017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 31117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 31217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 31317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * {@inheritDoc} 31417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 3158b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase * <p>Note that canceling a <code>AnimatorSet</code> also cancels all of the animations that it 3168b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase * is responsible for.</p> 31717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 31817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @SuppressWarnings("unchecked") 31917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @Override 32017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public void cancel() { 3217dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase mTerminated = true; 3228b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase if (isStarted()) { 3237dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase ArrayList<AnimatorListener> tmpListeners = null; 324e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase if (mListeners != null) { 3257dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase tmpListeners = (ArrayList<AnimatorListener>) mListeners.clone(); 326e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase for (AnimatorListener listener : tmpListeners) { 3277dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase listener.onAnimationCancel(this); 328e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase } 329e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase } 3307dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (mDelayAnim != null && mDelayAnim.isRunning()) { 3317dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase // If we're currently in the startDelay period, just cancel that animator and 3327dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase // send out the end event to all listeners 3337dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase mDelayAnim.cancel(); 3347dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } else if (mSortedNodes.size() > 0) { 3357dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase for (Node node : mSortedNodes) { 3367dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase node.animation.cancel(); 3377dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } 3387dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } 3397dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (tmpListeners != null) { 3407dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase for (AnimatorListener listener : tmpListeners) { 3417dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase listener.onAnimationEnd(this); 3427dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } 34317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 3448b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase mStarted = false; 34517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 34617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 34717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 34817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 34917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * {@inheritDoc} 35017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 351a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>Note that ending a <code>AnimatorSet</code> also ends all of the animations that it is 35217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * responsible for.</p> 35317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 35417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @Override 35517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public void end() { 3567dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase mTerminated = true; 3578b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase if (isStarted()) { 3587dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (mSortedNodes.size() != mNodes.size()) { 3597dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase // hasn't been started yet - sort the nodes now, then end them 3607dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase sortNodes(); 3617dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase for (Node node : mSortedNodes) { 3627dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (mSetListener == null) { 3637dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase mSetListener = new AnimatorSetListener(this); 3647dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } 3657dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase node.animation.addListener(mSetListener); 3661e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase } 3671e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase } 3687dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (mDelayAnim != null) { 3697dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase mDelayAnim.cancel(); 3707dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } 3717dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (mSortedNodes.size() > 0) { 3727dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase for (Node node : mSortedNodes) { 3737dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase node.animation.end(); 3747dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } 3757dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } 3767dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (mListeners != null) { 3777dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase ArrayList<AnimatorListener> tmpListeners = 3787dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase (ArrayList<AnimatorListener>) mListeners.clone(); 3797dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase for (AnimatorListener listener : tmpListeners) { 3807dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase listener.onAnimationEnd(this); 3817dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } 38217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 3838b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase mStarted = false; 38417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 38517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 38617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 38717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 3888b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase * Returns true if any of the child animations of this AnimatorSet have been started and have 3898b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase * not yet ended. 390a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @return Whether this AnimatorSet has been started and has not yet ended. 391673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase */ 392673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase @Override 393673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase public boolean isRunning() { 394673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase for (Node node : mNodes) { 395673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase if (node.animation.isRunning()) { 396673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase return true; 397673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase } 398673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase } 3998b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase return false; 4008b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase } 4018b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase 4028b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase @Override 4038b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase public boolean isStarted() { 4048b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase return mStarted; 405673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase } 406673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase 407673e42fafd4088970ec95e1f13c61dc83132c74eChet Haase /** 40821cd1389d2ef218b20994b617c57af120841a57fChet Haase * The amount of time, in milliseconds, to delay starting the animation after 40921cd1389d2ef218b20994b617c57af120841a57fChet Haase * {@link #start()} is called. 41021cd1389d2ef218b20994b617c57af120841a57fChet Haase * 41121cd1389d2ef218b20994b617c57af120841a57fChet Haase * @return the number of milliseconds to delay running the animation 41221cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 41321cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 41421cd1389d2ef218b20994b617c57af120841a57fChet Haase public long getStartDelay() { 41521cd1389d2ef218b20994b617c57af120841a57fChet Haase return mStartDelay; 41621cd1389d2ef218b20994b617c57af120841a57fChet Haase } 41721cd1389d2ef218b20994b617c57af120841a57fChet Haase 41821cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 41921cd1389d2ef218b20994b617c57af120841a57fChet Haase * The amount of time, in milliseconds, to delay starting the animation after 42021cd1389d2ef218b20994b617c57af120841a57fChet Haase * {@link #start()} is called. 42121cd1389d2ef218b20994b617c57af120841a57fChet Haase 42221cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param startDelay The amount of the delay, in milliseconds 42321cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 42421cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 42521cd1389d2ef218b20994b617c57af120841a57fChet Haase public void setStartDelay(long startDelay) { 4267bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui if (mStartDelay > 0) { 4277bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui mReversible = false; 4287bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui } 42921cd1389d2ef218b20994b617c57af120841a57fChet Haase mStartDelay = startDelay; 43021cd1389d2ef218b20994b617c57af120841a57fChet Haase } 43121cd1389d2ef218b20994b617c57af120841a57fChet Haase 43221cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 433a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Gets the length of each of the child animations of this AnimatorSet. This value may 434a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * be less than 0, which indicates that no duration has been set on this AnimatorSet 43521cd1389d2ef218b20994b617c57af120841a57fChet Haase * and each of the child animations will use their own duration. 43621cd1389d2ef218b20994b617c57af120841a57fChet Haase * 43721cd1389d2ef218b20994b617c57af120841a57fChet Haase * @return The length of the animation, in milliseconds, of each of the child 438a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * animations of this AnimatorSet. 43921cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 44021cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 44121cd1389d2ef218b20994b617c57af120841a57fChet Haase public long getDuration() { 44221cd1389d2ef218b20994b617c57af120841a57fChet Haase return mDuration; 44321cd1389d2ef218b20994b617c57af120841a57fChet Haase } 44421cd1389d2ef218b20994b617c57af120841a57fChet Haase 44521cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 446a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Sets the length of each of the current child animations of this AnimatorSet. By default, 447a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * each child animation will use its own duration. If the duration is set on the AnimatorSet, 44821cd1389d2ef218b20994b617c57af120841a57fChet Haase * then each child animation inherits this duration. 44921cd1389d2ef218b20994b617c57af120841a57fChet Haase * 45021cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param duration The length of the animation, in milliseconds, of each of the child 451a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * animations of this AnimatorSet. 45221cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 45321cd1389d2ef218b20994b617c57af120841a57fChet Haase @Override 4542794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase public AnimatorSet setDuration(long duration) { 45521cd1389d2ef218b20994b617c57af120841a57fChet Haase if (duration < 0) { 45621cd1389d2ef218b20994b617c57af120841a57fChet Haase throw new IllegalArgumentException("duration must be a value of zero or greater"); 45721cd1389d2ef218b20994b617c57af120841a57fChet Haase } 458c299a3384171e36fc9ab6d1011d8a589a7f344d1Chet Haase // Just record the value for now - it will be used later when the AnimatorSet starts 45921cd1389d2ef218b20994b617c57af120841a57fChet Haase mDuration = duration; 4602794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase return this; 46121cd1389d2ef218b20994b617c57af120841a57fChet Haase } 46221cd1389d2ef218b20994b617c57af120841a57fChet Haase 4632970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase @Override 4642970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase public void setupStartValues() { 4652970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase for (Node node : mNodes) { 4662970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase node.animation.setupStartValues(); 4672970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase } 4682970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase } 4692970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase 4702970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase @Override 4712970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase public void setupEndValues() { 4722970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase for (Node node : mNodes) { 4732970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase node.animation.setupEndValues(); 4742970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase } 4752970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase } 4762970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase 4778aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase @Override 4788aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase public void pause() { 4798aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase boolean previouslyPaused = mPaused; 4808aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase super.pause(); 4818aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase if (!previouslyPaused && mPaused) { 4828aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase if (mDelayAnim != null) { 4838aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase mDelayAnim.pause(); 4848aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase } else { 4858aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase for (Node node : mNodes) { 4868aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase node.animation.pause(); 4878aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase } 4888aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase } 4898aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase } 4908aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase } 4918aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase 4928aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase @Override 4938aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase public void resume() { 4948aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase boolean previouslyPaused = mPaused; 4958aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase super.resume(); 4968aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase if (previouslyPaused && !mPaused) { 4978aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase if (mDelayAnim != null) { 4988aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase mDelayAnim.resume(); 4998aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase } else { 5008aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase for (Node node : mNodes) { 5018aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase node.animation.resume(); 5028aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase } 5038aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase } 5048aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase } 5058aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase } 5068aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase 50721cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 50817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * {@inheritDoc} 50917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 510a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>Starting this <code>AnimatorSet</code> will, in turn, start the animations for which 51117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * it is responsible. The details of when exactly those animations are started depends on 51217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * the dependency relationships that have been set up between the animations. 51317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 51417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @SuppressWarnings("unchecked") 51517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @Override 51617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public void start() { 5177dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase mTerminated = false; 5188b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase mStarted = true; 5198aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase mPaused = false; 520010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase 521f5945a0c8bb868f978d9d0d22043a8b44464a86eJohn Reck for (Node node : mNodes) { 522f5945a0c8bb868f978d9d0d22043a8b44464a86eJohn Reck node.animation.setAllowRunningAsynchronously(false); 523f5945a0c8bb868f978d9d0d22043a8b44464a86eJohn Reck } 524f5945a0c8bb868f978d9d0d22043a8b44464a86eJohn Reck 525c299a3384171e36fc9ab6d1011d8a589a7f344d1Chet Haase if (mDuration >= 0) { 526c299a3384171e36fc9ab6d1011d8a589a7f344d1Chet Haase // If the duration was set on this AnimatorSet, pass it along to all child animations 527c299a3384171e36fc9ab6d1011d8a589a7f344d1Chet Haase for (Node node : mNodes) { 528c299a3384171e36fc9ab6d1011d8a589a7f344d1Chet Haase // TODO: don't set the duration of the timing-only nodes created by AnimatorSet to 529c299a3384171e36fc9ab6d1011d8a589a7f344d1Chet Haase // insert "play-after" delays 530c299a3384171e36fc9ab6d1011d8a589a7f344d1Chet Haase node.animation.setDuration(mDuration); 531c299a3384171e36fc9ab6d1011d8a589a7f344d1Chet Haase } 532c299a3384171e36fc9ab6d1011d8a589a7f344d1Chet Haase } 533430742f09063574271e6c4091de13b9b9e762514Chet Haase if (mInterpolator != null) { 534430742f09063574271e6c4091de13b9b9e762514Chet Haase for (Node node : mNodes) { 535430742f09063574271e6c4091de13b9b9e762514Chet Haase node.animation.setInterpolator(mInterpolator); 536430742f09063574271e6c4091de13b9b9e762514Chet Haase } 537430742f09063574271e6c4091de13b9b9e762514Chet Haase } 5387bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui // First, sort the nodes (if necessary). This will ensure that sortedNodes 53917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // contains the animation nodes in the correct order. 54017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase sortNodes(); 54117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 542e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase int numSortedNodes = mSortedNodes.size(); 543e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase for (int i = 0; i < numSortedNodes; ++i) { 544e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase Node node = mSortedNodes.get(i); 545e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase // First, clear out the old listeners 546e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase ArrayList<AnimatorListener> oldListeners = node.animation.getListeners(); 547e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase if (oldListeners != null && oldListeners.size() > 0) { 548d45204ba092312630a0e516ea7c247e594ce893bMartijn Coenen final ArrayList<AnimatorListener> clonedListeners = new 549d45204ba092312630a0e516ea7c247e594ce893bMartijn Coenen ArrayList<AnimatorListener>(oldListeners); 550d45204ba092312630a0e516ea7c247e594ce893bMartijn Coenen 551d45204ba092312630a0e516ea7c247e594ce893bMartijn Coenen for (AnimatorListener listener : clonedListeners) { 5527dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (listener instanceof DependencyListener || 5537dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase listener instanceof AnimatorSetListener) { 554e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase node.animation.removeListener(listener); 555e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase } 556e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase } 557e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase } 558e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase } 559e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase 56017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // nodesToStart holds the list of nodes to be started immediately. We don't want to 56117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // start the animations in the loop directly because we first need to set up 56217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // dependencies on all of the nodes. For example, we don't want to start an animation 56317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // when some other animation also wants to start when the first animation begins. 56421cd1389d2ef218b20994b617c57af120841a57fChet Haase final ArrayList<Node> nodesToStart = new ArrayList<Node>(); 5657c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numSortedNodes; ++i) { 5667c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Node node = mSortedNodes.get(i); 567a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (mSetListener == null) { 568a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase mSetListener = new AnimatorSetListener(this); 56917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 57017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node.dependencies == null || node.dependencies.size() == 0) { 57117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase nodesToStart.add(node); 57217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } else { 5737c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numDependencies = node.dependencies.size(); 5747c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int j = 0; j < numDependencies; ++j) { 5757c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Dependency dependency = node.dependencies.get(j); 57617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependency.node.animation.addListener( 577010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase new DependencyListener(this, node, dependency.rule)); 57817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 57917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.tmpDependencies = (ArrayList<Dependency>) node.dependencies.clone(); 58017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 581a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase node.animation.addListener(mSetListener); 58217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 58317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // Now that all dependencies are set up, start the animations that should be started. 58421cd1389d2ef218b20994b617c57af120841a57fChet Haase if (mStartDelay <= 0) { 58521cd1389d2ef218b20994b617c57af120841a57fChet Haase for (Node node : nodesToStart) { 58621cd1389d2ef218b20994b617c57af120841a57fChet Haase node.animation.start(); 58721cd1389d2ef218b20994b617c57af120841a57fChet Haase mPlayingSet.add(node.animation); 58821cd1389d2ef218b20994b617c57af120841a57fChet Haase } 58921cd1389d2ef218b20994b617c57af120841a57fChet Haase } else { 590e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase mDelayAnim = ValueAnimator.ofFloat(0f, 1f); 591e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase mDelayAnim.setDuration(mStartDelay); 592e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase mDelayAnim.addListener(new AnimatorListenerAdapter() { 593e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase boolean canceled = false; 594e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase public void onAnimationCancel(Animator anim) { 595e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase canceled = true; 596e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase } 597a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationEnd(Animator anim) { 598e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase if (!canceled) { 599e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase int numNodes = nodesToStart.size(); 600e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase for (int i = 0; i < numNodes; ++i) { 601e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase Node node = nodesToStart.get(i); 602e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase node.animation.start(); 603e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase mPlayingSet.add(node.animation); 604e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase } 60521cd1389d2ef218b20994b617c57af120841a57fChet Haase } 6068aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase mDelayAnim = null; 60721cd1389d2ef218b20994b617c57af120841a57fChet Haase } 60821cd1389d2ef218b20994b617c57af120841a57fChet Haase }); 609e2ab7ccd385cdb6517955c719e1d2b49771bedb6Chet Haase mDelayAnim.start(); 61017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 61117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mListeners != null) { 612a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ArrayList<AnimatorListener> tmpListeners = 613a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase (ArrayList<AnimatorListener>) mListeners.clone(); 6147c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numListeners = tmpListeners.size(); 6157c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numListeners; ++i) { 6167c608f25d494c8a0a671e7373efbb47ca635367eChet Haase tmpListeners.get(i).onAnimationStart(this); 6178b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase } 6188b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase } 6198b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase if (mNodes.size() == 0 && mStartDelay == 0) { 6208b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase // Handle unusual case where empty AnimatorSet is started - should send out 6218b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase // end event immediately since the event will not be sent out at all otherwise 6228b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase mStarted = false; 6238b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase if (mListeners != null) { 6248b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase ArrayList<AnimatorListener> tmpListeners = 6258b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase (ArrayList<AnimatorListener>) mListeners.clone(); 6268b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase int numListeners = tmpListeners.size(); 6278b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase for (int i = 0; i < numListeners; ++i) { 6282970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase tmpListeners.get(i).onAnimationEnd(this); 6292970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase } 63017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 63117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 63217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 63317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 63449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase @Override 635a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public AnimatorSet clone() { 636a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase final AnimatorSet anim = (AnimatorSet) super.clone(); 63749afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase /* 63849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * The basic clone() operation copies all items. This doesn't work very well for 639a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet, because it will copy references that need to be recreated and state 64049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * that may not apply. What we need to do now is put the clone in an uninitialized 64149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * state, with fresh, empty data structures. Then we will build up the nodes list 64249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * manually, as we clone each Node (and its animation). The clone will then be sorted, 64349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase * and will populate any appropriate lists, when it is started. 64449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase */ 645d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar final int nodeCount = mNodes.size(); 64649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase anim.mNeedsSort = true; 6477dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase anim.mTerminated = false; 6488b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase anim.mStarted = false; 649a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase anim.mPlayingSet = new ArrayList<Animator>(); 650d7444427d9f44b6b7448d4c21edca866132c8b59Doris Liu anim.mNodeMap = new ArrayMap<Animator, Node>(); 651d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar anim.mNodes = new ArrayList<Node>(nodeCount); 652d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar anim.mSortedNodes = new ArrayList<Node>(nodeCount); 6537bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui anim.mReversible = mReversible; 6546f6578e81c1df207da47e2e1337382341f271206Chet Haase anim.mSetListener = null; 65549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase 65649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // Walk through the old nodes list, cloning each node and adding it to the new nodemap. 657a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // One problem is that the old node dependencies point to nodes in the old AnimatorSet. 65849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // We need to track the old/new nodes in order to reconstruct the dependencies in the clone. 659d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar 660d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar for (int n = 0; n < nodeCount; n++) { 661d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar final Node node = mNodes.get(n); 66249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase Node nodeClone = node.clone(); 663d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar node.mTmpClone = nodeClone; 66449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase anim.mNodes.add(nodeClone); 66549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase anim.mNodeMap.put(nodeClone.animation, nodeClone); 66649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // Clear out the dependencies in the clone; we'll set these up manually later 66749afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase nodeClone.dependencies = null; 66849afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase nodeClone.tmpDependencies = null; 66949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase nodeClone.nodeDependents = null; 67049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase nodeClone.nodeDependencies = null; 671d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar 672a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // clear out any listeners that were set up by the AnimatorSet; these will 67349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // be set up when the clone's nodes are sorted 674d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar final ArrayList<AnimatorListener> cloneListeners = nodeClone.animation.getListeners(); 67549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase if (cloneListeners != null) { 676d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar for (int i = cloneListeners.size() - 1; i >= 0; i--) { 677d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar final AnimatorListener listener = cloneListeners.get(i); 678a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (listener instanceof AnimatorSetListener) { 679d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar cloneListeners.remove(i); 68049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 68149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 68249afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 68349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 68449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // Now that we've cloned all of the nodes, we're ready to walk through their 68549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase // dependencies, mapping the old dependencies to the new nodes 686d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar for (int n = 0; n < nodeCount; n++) { 687d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar final Node node = mNodes.get(n); 688d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar final Node clone = node.mTmpClone; 68949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase if (node.dependencies != null) { 690d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar clone.dependencies = new ArrayList<Dependency>(node.dependencies.size()); 691d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar final int depSize = node.dependencies.size(); 692d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar for (int i = 0; i < depSize; i ++) { 693d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar final Dependency dependency = node.dependencies.get(i); 694d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar Dependency cloneDependency = new Dependency(dependency.node.mTmpClone, 69549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase dependency.rule); 696d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar clone.dependencies.add(cloneDependency); 697d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar } 698d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar } 699d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar if (node.nodeDependents != null) { 700d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar clone.nodeDependents = new ArrayList<Node>(node.nodeDependents.size()); 701d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar for (Node dep : node.nodeDependents) { 702d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar clone.nodeDependents.add(dep.mTmpClone); 703d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar } 704d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar } 705d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar if (node.nodeDependencies != null) { 706d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar clone.nodeDependencies = new ArrayList<Node>(node.nodeDependencies.size()); 707d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar for (Node dep : node.nodeDependencies) { 708d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar clone.nodeDependencies.add(dep.mTmpClone); 70949afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 71049afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 71149afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 712d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar for (int n = 0; n < nodeCount; n++) { 713d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar mNodes.get(n).mTmpClone = null; 714d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar } 71549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase return anim; 71649afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 71749afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase 71817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 71917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * This class is the mechanism by which animations are started based on events in other 72017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * animations. If an animation has multiple dependencies on other animations, then 72117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * all dependencies must be satisfied before the animation is started. 72217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 723a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private static class DependencyListener implements AnimatorListener { 72417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 725a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private AnimatorSet mAnimatorSet; 726010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase 72717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // The node upon which the dependency is based. 72817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private Node mNode; 72917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 73017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // The Dependency rule (WITH or AFTER) that the listener should wait for on 73117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // the node 73217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private int mRule; 73317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 734a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public DependencyListener(AnimatorSet animatorSet, Node node, int rule) { 735a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase this.mAnimatorSet = animatorSet; 73617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase this.mNode = node; 73717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase this.mRule = rule; 73817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 73917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 74017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 741010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase * Ignore cancel events for now. We may want to handle this eventually, 742010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase * to prevent follow-on animations from running when some dependency 743010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase * animation is canceled. 74417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 745a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationCancel(Animator animation) { 74617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 74717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 74817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 74917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * An end event is received - see if this is an event we are listening for 75017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 751a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationEnd(Animator animation) { 75217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mRule == Dependency.AFTER) { 75317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase startIfReady(animation); 75417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 75517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 75617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 75717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 75817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Ignore repeat events for now 75917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 760a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationRepeat(Animator animation) { 76117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 76217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 76317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 76417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * A start event is received - see if this is an event we are listening for 76517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 766a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationStart(Animator animation) { 76717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mRule == Dependency.WITH) { 76817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase startIfReady(animation); 76917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 77017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 77117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 77217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 77317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Check whether the event received is one that the node was waiting for. 77417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * If so, mark it as complete and see whether it's time to start 77517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * the animation. 77617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param dependencyAnimation the animation that sent the event. 77717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 778a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private void startIfReady(Animator dependencyAnimation) { 7797dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (mAnimatorSet.mTerminated) { 780a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // if the parent AnimatorSet was canceled, then don't start any dependent anims 781010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase return; 782010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase } 78317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Dependency dependencyToRemove = null; 7847c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numDependencies = mNode.tmpDependencies.size(); 7857c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numDependencies; ++i) { 7867c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Dependency dependency = mNode.tmpDependencies.get(i); 78717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (dependency.rule == mRule && 78817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependency.node.animation == dependencyAnimation) { 78917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // rule fired - remove the dependency and listener and check to 79017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // see whether it's time to start the animation 79117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencyToRemove = dependency; 79217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencyAnimation.removeListener(this); 79317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase break; 79417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 79517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 79617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNode.tmpDependencies.remove(dependencyToRemove); 79717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mNode.tmpDependencies.size() == 0) { 79817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // all dependencies satisfied: start the animation 79917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNode.animation.start(); 800a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase mAnimatorSet.mPlayingSet.add(mNode.animation); 80117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 80217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 80317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 80417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 80517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 806a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private class AnimatorSetListener implements AnimatorListener { 80717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 808a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private AnimatorSet mAnimatorSet; 80917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 810a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase AnimatorSetListener(AnimatorSet animatorSet) { 811a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase mAnimatorSet = animatorSet; 81217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 81317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 814a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationCancel(Animator animation) { 8157dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (!mTerminated) { 8167dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase // Listeners are already notified of the AnimatorSet canceling in cancel(). 8177dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase // The logic below only kicks in when animations end normally 8187dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (mPlayingSet.size() == 0) { 8197dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (mListeners != null) { 8207dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase int numListeners = mListeners.size(); 8217dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase for (int i = 0; i < numListeners; ++i) { 8227dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase mListeners.get(i).onAnimationCancel(mAnimatorSet); 8237dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } 82417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 82517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 82617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 82717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 82817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 82917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase @SuppressWarnings("unchecked") 830a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationEnd(Animator animation) { 83117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase animation.removeListener(this); 83217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mPlayingSet.remove(animation); 833a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase Node animNode = mAnimatorSet.mNodeMap.get(animation); 8341e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase animNode.done = true; 8357dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (!mTerminated) { 8367dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase // Listeners are already notified of the AnimatorSet ending in cancel() or 8377dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase // end(); the logic below only kicks in when animations end normally 8387dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase ArrayList<Node> sortedNodes = mAnimatorSet.mSortedNodes; 8397dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase boolean allDone = true; 8407dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase int numSortedNodes = sortedNodes.size(); 8417dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase for (int i = 0; i < numSortedNodes; ++i) { 8427dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (!sortedNodes.get(i).done) { 8437dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase allDone = false; 8447dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase break; 8457dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } 846a6e4a1757728efc91627ece602b0899d75303659Chet Haase } 8477dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (allDone) { 8487dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase // If this was the last child animation to end, then notify listeners that this 8497dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase // AnimatorSet has ended 8507dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase if (mListeners != null) { 8517dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase ArrayList<AnimatorListener> tmpListeners = 8527dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase (ArrayList<AnimatorListener>) mListeners.clone(); 8537dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase int numListeners = tmpListeners.size(); 8547dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase for (int i = 0; i < numListeners; ++i) { 8557dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase tmpListeners.get(i).onAnimationEnd(mAnimatorSet); 8567dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase } 85717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 8588b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase mAnimatorSet.mStarted = false; 8598aa1ffb0ed292891030992c65df4e5dc8bd37524Chet Haase mAnimatorSet.mPaused = false; 86017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 86117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 86217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 86317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 86417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // Nothing to do 865a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationRepeat(Animator animation) { 86617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 86717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 86817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // Nothing to do 869a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void onAnimationStart(Animator animation) { 87017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 87117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 87217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 87317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 87417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 87517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * This method sorts the current set of nodes, if needed. The sort is a simple 87617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * DependencyGraph sort, which goes like this: 87717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - All nodes without dependencies become 'roots' 87817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - while roots list is not null 87917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - for each root r 88017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - add r to sorted list 88117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - remove r as a dependency from any other node 88217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * - any nodes with no dependencies are added to the roots list 88317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 88417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private void sortNodes() { 88517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mNeedsSort) { 88617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mSortedNodes.clear(); 88717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase ArrayList<Node> roots = new ArrayList<Node>(); 8887c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numNodes = mNodes.size(); 8897c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numNodes; ++i) { 8907c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Node node = mNodes.get(i); 89117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node.dependencies == null || node.dependencies.size() == 0) { 89217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase roots.add(node); 89317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 89417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 89517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase ArrayList<Node> tmpRoots = new ArrayList<Node>(); 89617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase while (roots.size() > 0) { 8977c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numRoots = roots.size(); 8987c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numRoots; ++i) { 8997c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Node root = roots.get(i); 90017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mSortedNodes.add(root); 90117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (root.nodeDependents != null) { 9027c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numDependents = root.nodeDependents.size(); 9037c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int j = 0; j < numDependents; ++j) { 9047c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Node node = root.nodeDependents.get(j); 90517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.nodeDependencies.remove(root); 90617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node.nodeDependencies.size() == 0) { 90717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase tmpRoots.add(node); 90817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 90917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 91017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 91117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 912010dbaa1236cf2dcdc62c29049468e90188acaaeChet Haase roots.clear(); 91317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase roots.addAll(tmpRoots); 91417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase tmpRoots.clear(); 91517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 91617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNeedsSort = false; 91717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mSortedNodes.size() != mNodes.size()) { 91817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase throw new IllegalStateException("Circular dependencies cannot exist" 919a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase + " in AnimatorSet"); 92017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 92117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } else { 92217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // Doesn't need sorting, but still need to add in the nodeDependencies list 92317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // because these get removed as the event listeners fire and the dependencies 92417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // are satisfied 9257c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numNodes = mNodes.size(); 9267c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int i = 0; i < numNodes; ++i) { 9277c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Node node = mNodes.get(i); 92817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node.dependencies != null && node.dependencies.size() > 0) { 9297c608f25d494c8a0a671e7373efbb47ca635367eChet Haase int numDependencies = node.dependencies.size(); 9307c608f25d494c8a0a671e7373efbb47ca635367eChet Haase for (int j = 0; j < numDependencies; ++j) { 9317c608f25d494c8a0a671e7373efbb47ca635367eChet Haase Dependency dependency = node.dependencies.get(j); 93217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node.nodeDependencies == null) { 93317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.nodeDependencies = new ArrayList<Node>(); 93417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 93517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (!node.nodeDependencies.contains(dependency.node)) { 93617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.nodeDependencies.add(dependency.node); 93717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 93817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 93917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 9407dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase // nodes are 'done' by default; they become un-done when started, and done 9417dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5Chet Haase // again when ended 9421e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase node.done = false; 94317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 94417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 94517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 94617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 94717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 9487bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui * @hide 9497bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui */ 9507bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui @Override 9517bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui public boolean canReverse() { 9527bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui if (!mReversible) { 9537bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui return false; 9547bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui } 9557bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui // Loop to make sure all the Nodes can reverse. 9567bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui for (Node node : mNodes) { 9577bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui if (!node.animation.canReverse() || node.animation.getStartDelay() > 0) { 9587bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui return false; 9597bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui } 9607bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui } 9617bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui return true; 9627bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui } 9637bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui 9647bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui /** 9657bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui * @hide 9667bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui */ 9677bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui @Override 9687bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui public void reverse() { 9697bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui if (canReverse()) { 9707bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui for (Node node : mNodes) { 9717bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui node.animation.reverse(); 9727bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui } 9737bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui } 9747bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui } 9757bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui 976d430753cba09acb07af8b313286f247c78a41a32Chet Haase @Override 977d430753cba09acb07af8b313286f247c78a41a32Chet Haase public String toString() { 978d430753cba09acb07af8b313286f247c78a41a32Chet Haase String returnVal = "AnimatorSet@" + Integer.toHexString(hashCode()) + "{"; 979d430753cba09acb07af8b313286f247c78a41a32Chet Haase boolean prevNeedsSort = mNeedsSort; 980d430753cba09acb07af8b313286f247c78a41a32Chet Haase sortNodes(); 981d430753cba09acb07af8b313286f247c78a41a32Chet Haase mNeedsSort = prevNeedsSort; 982d430753cba09acb07af8b313286f247c78a41a32Chet Haase for (Node node : mSortedNodes) { 983d430753cba09acb07af8b313286f247c78a41a32Chet Haase returnVal += "\n " + node.animation.toString(); 984d430753cba09acb07af8b313286f247c78a41a32Chet Haase } 985d430753cba09acb07af8b313286f247c78a41a32Chet Haase return returnVal + "\n}"; 986d430753cba09acb07af8b313286f247c78a41a32Chet Haase } 987d430753cba09acb07af8b313286f247c78a41a32Chet Haase 9887bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui /** 98917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Dependency holds information about the node that some other node is 99017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * dependent upon and the nature of that dependency. 99117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 99217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 99317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private static class Dependency { 99417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase static final int WITH = 0; // dependent node must start with this dependency node 99517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase static final int AFTER = 1; // dependent node must start when this dependency node finishes 99617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 99717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // The node that the other node with this Dependency is dependent upon 99817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public Node node; 99917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 100017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase // The nature of the dependency (WITH or AFTER) 100117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public int rule; 100217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 100317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public Dependency(Node node, int rule) { 100417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase this.node = node; 100517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase this.rule = rule; 100617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 100717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 100817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 100917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 1010a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * A Node is an embodiment of both the Animator that it wraps as well as 101117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * any dependencies that are associated with that Animation. This includes 101217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * both dependencies upon other nodes (in the dependencies list) as 101317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * well as dependencies of other nodes upon this (in the nodeDependents list). 101417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 101549afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase private static class Node implements Cloneable { 1016a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public Animator animation; 101717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 101817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 101917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * These are the dependencies that this node's animation has on other 102017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * nodes. For example, if this node's animation should begin with some 102117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * other animation ends, then there will be an item in this node's 102217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * dependencies list for that other animation's node. 102317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 102417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public ArrayList<Dependency> dependencies = null; 102517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 102617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 102717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * tmpDependencies is a runtime detail. We use the dependencies list for sorting. 102817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * But we also use the list to keep track of when multiple dependencies are satisfied, 102917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * but removing each dependency as it is satisfied. We do not want to remove 103017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * the dependency itself from the list, because we need to retain that information 1031a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * if the AnimatorSet is launched in the future. So we create a copy of the dependency 1032a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * list when the AnimatorSet starts and use this tmpDependencies list to track the 103317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * list of satisfied dependencies. 103417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 103517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public ArrayList<Dependency> tmpDependencies = null; 103617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 103717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 103817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * nodeDependencies is just a list of the nodes that this Node is dependent upon. 103917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * This information is used in sortNodes(), to determine when a node is a root. 104017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 104117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public ArrayList<Node> nodeDependencies = null; 104217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 104317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 104417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * nodeDepdendents is the list of nodes that have this node as a dependency. This 104517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * is a utility field used in sortNodes to facilitate removing this node as a 104617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * dependency when it is a root node. 104717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 104817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public ArrayList<Node> nodeDependents = null; 104917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 105017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 10511e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase * Flag indicating whether the animation in this node is finished. This flag 1052a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * is used by AnimatorSet to check, as each animation ends, whether all child animations 1053a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * are done and it's time to send out an end event for the entire AnimatorSet. 10541e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase */ 10551e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase public boolean done = false; 10561e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase 10571e0ac5a1063d00670f4dc7ca5b120ef2836f9e8fChet Haase /** 1058d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar * Temporary field to hold the clone in AnimatorSet#clone. Cleaned after clone is complete 1059d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar */ 1060d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar private Node mTmpClone = null; 1061d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar 1062d422dc358f0100106dc07d7b903201eb9b043b11Yigit Boyar /** 106317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Constructs the Node with the animation that it encapsulates. A Node has no 106417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * dependencies by default; dependencies are added via the addDependency() 106517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * method. 106617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 106717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param animation The animation that the Node encapsulates. 106817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 1069a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public Node(Animator animation) { 107017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase this.animation = animation; 107117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 107217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 107317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 107417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Add a dependency to this Node. The dependency includes information about the 107517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * node that this node is dependency upon and the nature of the dependency. 107617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param dependency 107717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 107817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public void addDependency(Dependency dependency) { 107917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (dependencies == null) { 108017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencies = new ArrayList<Dependency>(); 108117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase nodeDependencies = new ArrayList<Node>(); 108217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 108317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencies.add(dependency); 108417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (!nodeDependencies.contains(dependency.node)) { 108517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase nodeDependencies.add(dependency.node); 108617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 108717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Node dependencyNode = dependency.node; 108817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (dependencyNode.nodeDependents == null) { 108917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencyNode.nodeDependents = new ArrayList<Node>(); 109017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 109117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase dependencyNode.nodeDependents.add(this); 109217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 109349afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase 109449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase @Override 109521cd1389d2ef218b20994b617c57af120841a57fChet Haase public Node clone() { 109621cd1389d2ef218b20994b617c57af120841a57fChet Haase try { 109721cd1389d2ef218b20994b617c57af120841a57fChet Haase Node node = (Node) super.clone(); 1098b1e80d826b860203cc966d56584f9d83f5636bc0ztenghui node.animation = animation.clone(); 1099b1e80d826b860203cc966d56584f9d83f5636bc0ztenghui node.done = false; 110021cd1389d2ef218b20994b617c57af120841a57fChet Haase return node; 110121cd1389d2ef218b20994b617c57af120841a57fChet Haase } catch (CloneNotSupportedException e) { 110221cd1389d2ef218b20994b617c57af120841a57fChet Haase throw new AssertionError(); 110321cd1389d2ef218b20994b617c57af120841a57fChet Haase } 110449afa5bc100e5d4c069fea980dd6b09501f56397Chet Haase } 110517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 110617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 110717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 110817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * The <code>Builder</code> object is a utility class to facilitate adding animations to a 1109a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <code>AnimatorSet</code> along with the relationships between the various animations. The 111017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * intention of the <code>Builder</code> methods, along with the {@link 11118b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase * AnimatorSet#play(Animator) play()} method of <code>AnimatorSet</code> is to make it possible 11128b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase * to express the dependency relationships of animations in a natural way. Developers can also 11138b699792b677bd4dd8442b32641ac09d48fdd79cChet Haase * use the {@link AnimatorSet#playTogether(Animator[]) playTogether()} and {@link 1114a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet#playSequentially(Animator[]) playSequentially()} methods if these suit the need, 1115a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * but it might be easier in some situations to express the AnimatorSet of animations in pairs. 111617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p/> 111717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p>The <code>Builder</code> object cannot be constructed directly, but is rather constructed 1118a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * internally via a call to {@link AnimatorSet#play(Animator)}.</p> 111917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p/> 1120a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>For example, this sets up a AnimatorSet to play anim1 and anim2 at the same time, anim3 to 112117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * play when anim2 finishes, and anim4 to play when anim3 finishes:</p> 112217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <pre> 1123a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet s = new AnimatorSet(); 112417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim1).with(anim2); 112517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim2).before(anim3); 112617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim4).after(anim3); 112717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * </pre> 112817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p/> 1129a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * <p>Note in the example that both {@link Builder#before(Animator)} and {@link 1130a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Builder#after(Animator)} are used. These are just different ways of expressing the same 113117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * relationship and are provided to make it easier to say things in a way that is more natural, 113217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * depending on the situation.</p> 113317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p/> 113417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p>It is possible to make several calls into the same <code>Builder</code> object to express 113517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * multiple relationships. However, note that it is only the animation passed into the initial 1136a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} method that is the dependency in any of the successive 113717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * calls to the <code>Builder</code> object. For example, the following code starts both anim2 113817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * and anim3 when anim1 ends; there is no direct dependency relationship between anim2 and 113917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * anim3: 114017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <pre> 1141a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet s = new AnimatorSet(); 114217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim1).before(anim2).before(anim3); 114317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * </pre> 114417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * If the desired result is to play anim1 then anim2 then anim3, this code expresses the 114517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * relationship correctly:</p> 114617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <pre> 1147a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * AnimatorSet s = new AnimatorSet(); 114817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim1).before(anim2); 114917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * s.play(anim2).before(anim3); 115017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * </pre> 115117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p/> 115217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * <p>Note that it is possible to express relationships that cannot be resolved and will not 115317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * result in sensible results. For example, <code>play(anim1).after(anim1)</code> makes no 115417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * sense. In general, circular dependencies like this one (or more indirect ones where a depends 1155a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * on b, which depends on c, which depends on a) should be avoided. Only create AnimatorSets 1156a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * that can boil down to a simple, one-way relationship of animations starting with, before, and 115717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * after other, different, animations.</p> 115817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 115917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase public class Builder { 116017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 116117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 116217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * This tracks the current node being processed. It is supplied to the play() method 1163a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * of AnimatorSet and passed into the constructor of Builder. 116417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 116517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase private Node mCurrentNode; 116617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 116717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 1168a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * package-private constructor. Builders are only constructed by AnimatorSet, when the 116917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * play() method is called. 117017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 117117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param anim The animation that is the dependency for the other animations passed into 117217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * the other methods of this Builder object. 117317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 1174a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase Builder(Animator anim) { 117517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mCurrentNode = mNodeMap.get(anim); 117617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (mCurrentNode == null) { 117717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mCurrentNode = new Node(anim); 117817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodeMap.put(anim, mCurrentNode); 117917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodes.add(mCurrentNode); 118017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 118117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 118217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 118317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 118417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Sets up the given animation to play at the same time as the animation supplied in the 1185a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object. 118617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 118717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param anim The animation that will play when the animation supplied to the 1188a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} method starts. 118917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 11902970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase public Builder with(Animator anim) { 119117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Node node = mNodeMap.get(anim); 119217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node == null) { 119317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node = new Node(anim); 119417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodeMap.put(anim, node); 119517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodes.add(node); 119617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 119717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Dependency dependency = new Dependency(mCurrentNode, Dependency.WITH); 119817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.addDependency(dependency); 11992970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase return this; 120017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 120117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 120217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 120317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Sets up the given animation to play when the animation supplied in the 1204a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object 120517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * ends. 120617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 120717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param anim The animation that will play when the animation supplied to the 1208a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} method ends. 120917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 12102970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase public Builder before(Animator anim) { 12117bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui mReversible = false; 121217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Node node = mNodeMap.get(anim); 121317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node == null) { 121417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node = new Node(anim); 121517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodeMap.put(anim, node); 121617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodes.add(node); 121717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 121817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Dependency dependency = new Dependency(mCurrentNode, Dependency.AFTER); 121917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node.addDependency(dependency); 12202970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase return this; 122117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 122217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 122317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 122417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Sets up the given animation to play when the animation supplied in the 1225a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object 122617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * to start when the animation supplied in this method call ends. 122717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 122817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param anim The animation whose end will cause the animation supplied to the 1229a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} method to play. 123017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 12312970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase public Builder after(Animator anim) { 12327bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui mReversible = false; 123317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Node node = mNodeMap.get(anim); 123417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase if (node == null) { 123517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase node = new Node(anim); 123617fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodeMap.put(anim, node); 123717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mNodes.add(node); 123817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 123917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase Dependency dependency = new Dependency(node, Dependency.AFTER); 124017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase mCurrentNode.addDependency(dependency); 12412970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase return this; 124217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 124317fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 124417fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase /** 124517fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * Sets up the animation supplied in the 1246a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object 124717fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * to play when the given amount of time elapses. 124817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * 124917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * @param delay The number of milliseconds that should elapse before the 125017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase * animation starts. 125117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase */ 12522970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase public Builder after(long delay) { 1253a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase // setup dummy ValueAnimator just to run the clock 12542794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); 12552794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase anim.setDuration(delay); 12562794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase after(anim); 12572970c499388b4dcd1232cd622a9b80b395eeb2b4Chet Haase return this; 125817fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 125917fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 126017fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase } 126117fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase 126217fb4b0d1cfbad1f026fec704c86640f070b4c2fChet Haase} 1263