121cd1389d2ef218b20994b617c57af120841a57fChet Haase/* 221cd1389d2ef218b20994b617c57af120841a57fChet Haase * Copyright (C) 2010 The Android Open Source Project 321cd1389d2ef218b20994b617c57af120841a57fChet Haase * 421cd1389d2ef218b20994b617c57af120841a57fChet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 521cd1389d2ef218b20994b617c57af120841a57fChet Haase * you may not use this file except in compliance with the License. 621cd1389d2ef218b20994b617c57af120841a57fChet Haase * You may obtain a copy of the License at 721cd1389d2ef218b20994b617c57af120841a57fChet Haase * 821cd1389d2ef218b20994b617c57af120841a57fChet Haase * http://www.apache.org/licenses/LICENSE-2.0 921cd1389d2ef218b20994b617c57af120841a57fChet Haase * 1021cd1389d2ef218b20994b617c57af120841a57fChet Haase * Unless required by applicable law or agreed to in writing, software 1121cd1389d2ef218b20994b617c57af120841a57fChet Haase * distributed under the License is distributed on an "AS IS" BASIS, 1221cd1389d2ef218b20994b617c57af120841a57fChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1321cd1389d2ef218b20994b617c57af120841a57fChet Haase * See the License for the specific language governing permissions and 1421cd1389d2ef218b20994b617c57af120841a57fChet Haase * limitations under the License. 1521cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 1621cd1389d2ef218b20994b617c57af120841a57fChet Haase 1721cd1389d2ef218b20994b617c57af120841a57fChet Haasepackage android.animation; 1821cd1389d2ef218b20994b617c57af120841a57fChet Haase 1921cd1389d2ef218b20994b617c57af120841a57fChet Haaseimport android.view.View; 2021cd1389d2ef218b20994b617c57af120841a57fChet Haaseimport android.view.ViewGroup; 21cca2c9807206f320bd41bf8656a227e4f249e4baChet Haaseimport android.view.ViewParent; 2221cd1389d2ef218b20994b617c57af120841a57fChet Haaseimport android.view.ViewTreeObserver; 2321cd1389d2ef218b20994b617c57af120841a57fChet Haaseimport android.view.animation.AccelerateDecelerateInterpolator; 2421cd1389d2ef218b20994b617c57af120841a57fChet Haaseimport android.view.animation.DecelerateInterpolator; 2521cd1389d2ef218b20994b617c57af120841a57fChet Haase 2621cd1389d2ef218b20994b617c57af120841a57fChet Haaseimport java.util.ArrayList; 271a76dcd6d1e30f92668b5df309398d545cef9aceChet Haaseimport java.util.Collection; 2821cd1389d2ef218b20994b617c57af120841a57fChet Haaseimport java.util.HashMap; 29eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haaseimport java.util.LinkedHashMap; 3021cd1389d2ef218b20994b617c57af120841a57fChet Haaseimport java.util.List; 3121cd1389d2ef218b20994b617c57af120841a57fChet Haase 3221cd1389d2ef218b20994b617c57af120841a57fChet Haase/** 3321cd1389d2ef218b20994b617c57af120841a57fChet Haase * This class enables automatic animations on layout changes in ViewGroup objects. To enable 3421cd1389d2ef218b20994b617c57af120841a57fChet Haase * transitions for a layout container, create a LayoutTransition object and set it on any 3521cd1389d2ef218b20994b617c57af120841a57fChet Haase * ViewGroup by calling {@link ViewGroup#setLayoutTransition(LayoutTransition)}. This will cause 3621cd1389d2ef218b20994b617c57af120841a57fChet Haase * default animations to run whenever items are added to or removed from that container. To specify 37a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * custom animations, use the {@link LayoutTransition#setAnimator(int, Animator) 38a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * setAnimator()} method. 3921cd1389d2ef218b20994b617c57af120841a57fChet Haase * 40daf98e941e140e8739458126640183b9f296a2abChet Haase * <p>One of the core concepts of these transition animations is that there are two types of 4121cd1389d2ef218b20994b617c57af120841a57fChet Haase * changes that cause the transition and four different animations that run because of 4221cd1389d2ef218b20994b617c57af120841a57fChet Haase * those changes. The changes that trigger the transition are items being added to a container 4321cd1389d2ef218b20994b617c57af120841a57fChet Haase * (referred to as an "appearing" transition) or removed from a container (also known as 44daf98e941e140e8739458126640183b9f296a2abChet Haase * "disappearing"). Setting the visibility of views (between GONE and VISIBLE) will trigger 45daf98e941e140e8739458126640183b9f296a2abChet Haase * the same add/remove logic. The animations that run due to those events are one that animates 4621cd1389d2ef218b20994b617c57af120841a57fChet Haase * items being added, one that animates items being removed, and two that animate the other 4721cd1389d2ef218b20994b617c57af120841a57fChet Haase * items in the container that change due to the add/remove occurrence. Users of 4821cd1389d2ef218b20994b617c57af120841a57fChet Haase * the transition may want different animations for the changing items depending on whether 49daf98e941e140e8739458126640183b9f296a2abChet Haase * they are changing due to an appearing or disappearing event, so there is one animation for 5021cd1389d2ef218b20994b617c57af120841a57fChet Haase * each of these variations of the changing event. Most of the API of this class is concerned 5121cd1389d2ef218b20994b617c57af120841a57fChet Haase * with setting up the basic properties of the animations used in these four situations, 5221cd1389d2ef218b20994b617c57af120841a57fChet Haase * or with setting up custom animations for any or all of the four.</p> 5321cd1389d2ef218b20994b617c57af120841a57fChet Haase * 54c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * <p>By default, the DISAPPEARING animation begins immediately, as does the CHANGE_APPEARING 55c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * animation. The other animations begin after a delay that is set to the default duration 56c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * of the animations. This behavior facilitates a sequence of animations in transitions as 57c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * follows: when an item is being added to a layout, the other children of that container will 58c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * move first (thus creating space for the new item), then the appearing animation will run to 59c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * animate the item being added. Conversely, when an item is removed from a container, the 60c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * animation to remove it will run first, then the animations of the other children in the 61c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * layout will run (closing the gap created in the layout when the item was removed). If this 62c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * default choreography behavior is not desired, the {@link #setDuration(int, long)} and 63c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * {@link #setStartDelay(int, long)} of any or all of the animations can be changed as 64c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * appropriate.</p> 65c54ed966f78b9ee8117931859d62faa6f11fe018Chet Haase * 6621cd1389d2ef218b20994b617c57af120841a57fChet Haase * <p>The animations specified for the transition, both the defaults and any custom animations 6721cd1389d2ef218b20994b617c57af120841a57fChet Haase * set on the transition object, are templates only. That is, these animations exist to hold the 6821cd1389d2ef218b20994b617c57af120841a57fChet Haase * basic animation properties, such as the duration, start delay, and properties being animated. 6921cd1389d2ef218b20994b617c57af120841a57fChet Haase * But the actual target object, as well as the start and end values for those properties, are 7021cd1389d2ef218b20994b617c57af120841a57fChet Haase * set automatically in the process of setting up the transition each time it runs. Each of the 7121cd1389d2ef218b20994b617c57af120841a57fChet Haase * animations is cloned from the original copy and the clone is then populated with the dynamic 7221cd1389d2ef218b20994b617c57af120841a57fChet Haase * values of the target being animated (such as one of the items in a layout container that is 7321cd1389d2ef218b20994b617c57af120841a57fChet Haase * moving as a result of the layout event) as well as the values that are changing (such as the 7421cd1389d2ef218b20994b617c57af120841a57fChet Haase * position and size of that object). The actual values that are pushed to each animation 7521cd1389d2ef218b20994b617c57af120841a57fChet Haase * depends on what properties are specified for the animation. For example, the default 76cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * CHANGE_APPEARING animation animates the <code>left</code>, <code>top</code>, <code>right</code>, 77cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * <code>bottom</code>, <code>scrollX</code>, and <code>scrollY</code> properties. 78cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * Values for these properties are updated with the pre- and post-layout 7921cd1389d2ef218b20994b617c57af120841a57fChet Haase * values when the transition begins. Custom animations will be similarly populated with 80a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * the target and values being animated, assuming they use ObjectAnimator objects with 8121cd1389d2ef218b20994b617c57af120841a57fChet Haase * property names that are known on the target object.</p> 82daf98e941e140e8739458126640183b9f296a2abChet Haase * 83daf98e941e140e8739458126640183b9f296a2abChet Haase * <p>This class, and the associated XML flag for containers, animateLayoutChanges="true", 84daf98e941e140e8739458126640183b9f296a2abChet Haase * provides a simple utility meant for automating changes in straightforward situations. 85daf98e941e140e8739458126640183b9f296a2abChet Haase * Using LayoutTransition at multiple levels of a nested view hierarchy may not work due to the 86daf98e941e140e8739458126640183b9f296a2abChet Haase * interrelationship of the various levels of layout. Also, a container that is being scrolled 87daf98e941e140e8739458126640183b9f296a2abChet Haase * at the same time as items are being added or removed is probably not a good candidate for 88daf98e941e140e8739458126640183b9f296a2abChet Haase * this utility, because the before/after locations calculated by LayoutTransition 89daf98e941e140e8739458126640183b9f296a2abChet Haase * may not match the actual locations when the animations finish due to the container 90daf98e941e140e8739458126640183b9f296a2abChet Haase * being scrolled as the animations are running. You can work around that 91daf98e941e140e8739458126640183b9f296a2abChet Haase * particular issue by disabling the 'changing' animations by setting the CHANGE_APPEARING 92daf98e941e140e8739458126640183b9f296a2abChet Haase * and CHANGE_DISAPPEARING animations to null, and setting the startDelay of the 93daf98e941e140e8739458126640183b9f296a2abChet Haase * other animations appropriately.</p> 9421cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 9521cd1389d2ef218b20994b617c57af120841a57fChet Haasepublic class LayoutTransition { 9621cd1389d2ef218b20994b617c57af120841a57fChet Haase 9721cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 9821cd1389d2ef218b20994b617c57af120841a57fChet Haase * A flag indicating the animation that runs on those items that are changing 9921cd1389d2ef218b20994b617c57af120841a57fChet Haase * due to a new item appearing in the container. 10021cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 10121cd1389d2ef218b20994b617c57af120841a57fChet Haase public static final int CHANGE_APPEARING = 0; 10221cd1389d2ef218b20994b617c57af120841a57fChet Haase 10321cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 10421cd1389d2ef218b20994b617c57af120841a57fChet Haase * A flag indicating the animation that runs on those items that are changing 1059e90a9953b65ae575ec8db3989857e0c145724b1Chet Haase * due to an item disappearing from the container. 10621cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 10721cd1389d2ef218b20994b617c57af120841a57fChet Haase public static final int CHANGE_DISAPPEARING = 1; 10821cd1389d2ef218b20994b617c57af120841a57fChet Haase 10921cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 1109e90a9953b65ae575ec8db3989857e0c145724b1Chet Haase * A flag indicating the animation that runs on those items that are appearing 1119e90a9953b65ae575ec8db3989857e0c145724b1Chet Haase * in the container. 11221cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 11321cd1389d2ef218b20994b617c57af120841a57fChet Haase public static final int APPEARING = 2; 11421cd1389d2ef218b20994b617c57af120841a57fChet Haase 11521cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 1169e90a9953b65ae575ec8db3989857e0c145724b1Chet Haase * A flag indicating the animation that runs on those items that are disappearing 1179e90a9953b65ae575ec8db3989857e0c145724b1Chet Haase * from the container. 11821cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 11921cd1389d2ef218b20994b617c57af120841a57fChet Haase public static final int DISAPPEARING = 3; 12021cd1389d2ef218b20994b617c57af120841a57fChet Haase 12121cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 1227dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * A flag indicating the animation that runs on those items that are changing 1237dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * due to a layout change not caused by items being added to or removed 1247dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * from the container. This transition type is not enabled by default; it can be 1257dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * enabled via {@link #enableTransitionType(int)}. 1267dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase */ 1277dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase public static final int CHANGING = 4; 1287dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase 1297dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase /** 1307dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * Private bit fields used to set the collection of enabled transition types for 1317dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * mTransitionTypes. 1327dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase */ 1337dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase private static final int FLAG_APPEARING = 0x01; 1347dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase private static final int FLAG_DISAPPEARING = 0x02; 1357dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase private static final int FLAG_CHANGE_APPEARING = 0x04; 1367dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase private static final int FLAG_CHANGE_DISAPPEARING = 0x08; 1377dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase private static final int FLAG_CHANGING = 0x10; 1387dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase 1397dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase /** 14021cd1389d2ef218b20994b617c57af120841a57fChet Haase * These variables hold the animations that are currently used to run the transition effects. 14121cd1389d2ef218b20994b617c57af120841a57fChet Haase * These animations are set to defaults, but can be changed to custom animations by 142a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * calls to setAnimator(). 14321cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 144a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private Animator mDisappearingAnim = null; 145a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private Animator mAppearingAnim = null; 146a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private Animator mChangingAppearingAnim = null; 147a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private Animator mChangingDisappearingAnim = null; 1487dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase private Animator mChangingAnim = null; 14921cd1389d2ef218b20994b617c57af120841a57fChet Haase 15021cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 15121cd1389d2ef218b20994b617c57af120841a57fChet Haase * These are the default animations, defined in the constructor, that will be used 15221cd1389d2ef218b20994b617c57af120841a57fChet Haase * unless the user specifies custom animations. 15321cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 1547dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase private static ObjectAnimator defaultChange; 155a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private static ObjectAnimator defaultChangeIn; 156a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private static ObjectAnimator defaultChangeOut; 157a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private static ObjectAnimator defaultFadeIn; 158a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase private static ObjectAnimator defaultFadeOut; 15921cd1389d2ef218b20994b617c57af120841a57fChet Haase 16021cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 16121cd1389d2ef218b20994b617c57af120841a57fChet Haase * The default duration used by all animations. 16221cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 16321cd1389d2ef218b20994b617c57af120841a57fChet Haase private static long DEFAULT_DURATION = 300; 16421cd1389d2ef218b20994b617c57af120841a57fChet Haase 16521cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 1667dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * The durations of the different animations 16721cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 16821cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mChangingAppearingDuration = DEFAULT_DURATION; 16921cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mChangingDisappearingDuration = DEFAULT_DURATION; 1707dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase private long mChangingDuration = DEFAULT_DURATION; 17121cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mAppearingDuration = DEFAULT_DURATION; 17221cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mDisappearingDuration = DEFAULT_DURATION; 17321cd1389d2ef218b20994b617c57af120841a57fChet Haase 17421cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 1757dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * The start delays of the different animations. Note that the default behavior of 17621cd1389d2ef218b20994b617c57af120841a57fChet Haase * the appearing item is the default duration, since it should wait for the items to move 17721cd1389d2ef218b20994b617c57af120841a57fChet Haase * before fading it. Same for the changing animation when disappearing; it waits for the item 17821cd1389d2ef218b20994b617c57af120841a57fChet Haase * to fade out before moving the other items. 17921cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 18021cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mAppearingDelay = DEFAULT_DURATION; 18121cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mDisappearingDelay = 0; 18221cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mChangingAppearingDelay = 0; 18321cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mChangingDisappearingDelay = DEFAULT_DURATION; 1847dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase private long mChangingDelay = 0; 18521cd1389d2ef218b20994b617c57af120841a57fChet Haase 18621cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 1877dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * The inter-animation delays used on the changing animations 18821cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 18921cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mChangingAppearingStagger = 0; 19021cd1389d2ef218b20994b617c57af120841a57fChet Haase private long mChangingDisappearingStagger = 0; 1917dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase private long mChangingStagger = 0; 19221cd1389d2ef218b20994b617c57af120841a57fChet Haase 19321cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 19433d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase * Static interpolators - these are stateless and can be shared across the instances 19533d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase */ 19633d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private static TimeInterpolator ACCEL_DECEL_INTERPOLATOR = 19733d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase new AccelerateDecelerateInterpolator(); 19833d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private static TimeInterpolator DECEL_INTERPOLATOR = new DecelerateInterpolator(); 19933d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private static TimeInterpolator sAppearingInterpolator = ACCEL_DECEL_INTERPOLATOR; 20033d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private static TimeInterpolator sDisappearingInterpolator = ACCEL_DECEL_INTERPOLATOR; 20133d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private static TimeInterpolator sChangingAppearingInterpolator = DECEL_INTERPOLATOR; 20233d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private static TimeInterpolator sChangingDisappearingInterpolator = DECEL_INTERPOLATOR; 20333d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private static TimeInterpolator sChangingInterpolator = DECEL_INTERPOLATOR; 20433d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase 20533d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase /** 20621cd1389d2ef218b20994b617c57af120841a57fChet Haase * The default interpolators used for the animations 20721cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 20833d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private TimeInterpolator mAppearingInterpolator = sAppearingInterpolator; 20933d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private TimeInterpolator mDisappearingInterpolator = sDisappearingInterpolator; 21033d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private TimeInterpolator mChangingAppearingInterpolator = sChangingAppearingInterpolator; 21133d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private TimeInterpolator mChangingDisappearingInterpolator = sChangingDisappearingInterpolator; 21233d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase private TimeInterpolator mChangingInterpolator = sChangingInterpolator; 21321cd1389d2ef218b20994b617c57af120841a57fChet Haase 21421cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 215e64ea87f966e995f5e1a77f991b9da0ed21ffab0Chet Haase * These hashmaps are used to store the animations that are currently running as part of 21621cd1389d2ef218b20994b617c57af120841a57fChet Haase * the transition. The reason for this is that a further layout event should cause 21721cd1389d2ef218b20994b617c57af120841a57fChet Haase * existing animations to stop where they are prior to starting new animations. So 21821cd1389d2ef218b20994b617c57af120841a57fChet Haase * we cache all of the current animations in this map for possible cancellation on 219eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase * another layout event. LinkedHashMaps are used to preserve the order in which animations 220eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase * are inserted, so that we process events (such as setting up start values) in the same order. 22121cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 222eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase private final HashMap<View, Animator> pendingAnimations = 223cbda9104d029a8420786bd17725e8b1fb0c4c188Ben Komalo new HashMap<View, Animator>(); 224eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase private final LinkedHashMap<View, Animator> currentChangingAnimations = 225eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase new LinkedHashMap<View, Animator>(); 226eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase private final LinkedHashMap<View, Animator> currentAppearingAnimations = 227eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase new LinkedHashMap<View, Animator>(); 228eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase private final LinkedHashMap<View, Animator> currentDisappearingAnimations = 229eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase new LinkedHashMap<View, Animator>(); 23021cd1389d2ef218b20994b617c57af120841a57fChet Haase 23121cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 23221cd1389d2ef218b20994b617c57af120841a57fChet Haase * This hashmap is used to track the listeners that have been added to the children of 23321cd1389d2ef218b20994b617c57af120841a57fChet Haase * a container. When a layout change occurs, an animation is created for each View, so that 23421cd1389d2ef218b20994b617c57af120841a57fChet Haase * the pre-layout values can be cached in that animation. Then a listener is added to the 23521cd1389d2ef218b20994b617c57af120841a57fChet Haase * view to see whether the layout changes the bounds of that view. If so, the animation 23621cd1389d2ef218b20994b617c57af120841a57fChet Haase * is set with the final values and then run. If not, the animation is not started. When 23721cd1389d2ef218b20994b617c57af120841a57fChet Haase * the process of setting up and running all appropriate animations is done, we need to 23821cd1389d2ef218b20994b617c57af120841a57fChet Haase * remove these listeners and clear out the map. 23921cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 240cbda9104d029a8420786bd17725e8b1fb0c4c188Ben Komalo private final HashMap<View, View.OnLayoutChangeListener> layoutChangeListenerMap = 24121cd1389d2ef218b20994b617c57af120841a57fChet Haase new HashMap<View, View.OnLayoutChangeListener>(); 24221cd1389d2ef218b20994b617c57af120841a57fChet Haase 24321cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 24421cd1389d2ef218b20994b617c57af120841a57fChet Haase * Used to track the current delay being assigned to successive animations as they are 24521cd1389d2ef218b20994b617c57af120841a57fChet Haase * started. This value is incremented for each new animation, then zeroed before the next 24621cd1389d2ef218b20994b617c57af120841a57fChet Haase * transition begins. 24721cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 24821cd1389d2ef218b20994b617c57af120841a57fChet Haase private long staggerDelay; 24921cd1389d2ef218b20994b617c57af120841a57fChet Haase 25021cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 2517dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * These are the types of transition animations that the LayoutTransition is reacting 2527dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * to. By default, appearing/disappearing and the change animations related to them are 2537dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * enabled (not CHANGING). 2547dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase */ 2557dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase private int mTransitionTypes = FLAG_CHANGE_APPEARING | FLAG_CHANGE_DISAPPEARING | 2567dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase FLAG_APPEARING | FLAG_DISAPPEARING; 2577dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase /** 25821cd1389d2ef218b20994b617c57af120841a57fChet Haase * The set of listeners that should be notified when APPEARING/DISAPPEARING transitions 25921cd1389d2ef218b20994b617c57af120841a57fChet Haase * start and end. 26021cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 26121cd1389d2ef218b20994b617c57af120841a57fChet Haase private ArrayList<TransitionListener> mListeners; 26221cd1389d2ef218b20994b617c57af120841a57fChet Haase 263cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase /** 264cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * Controls whether changing animations automatically animate the parent hierarchy as well. 265cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * This behavior prevents artifacts when wrap_content layouts snap to the end state as the 266cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * transition begins, causing visual glitches and clipping. 267cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * Default value is true. 268cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase */ 269cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase private boolean mAnimateParentHierarchy = true; 270cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 27121cd1389d2ef218b20994b617c57af120841a57fChet Haase 27221cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 27321cd1389d2ef218b20994b617c57af120841a57fChet Haase * Constructs a LayoutTransition object. By default, the object will listen to layout 27421cd1389d2ef218b20994b617c57af120841a57fChet Haase * events on any ViewGroup that it is set on and will run default animations for each 27521cd1389d2ef218b20994b617c57af120841a57fChet Haase * type of layout event. 27621cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 27721cd1389d2ef218b20994b617c57af120841a57fChet Haase public LayoutTransition() { 27821cd1389d2ef218b20994b617c57af120841a57fChet Haase if (defaultChangeIn == null) { 27921cd1389d2ef218b20994b617c57af120841a57fChet Haase // "left" is just a placeholder; we'll put real properties/values in when needed 2802794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1); 2812794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1); 2822794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 1); 2832794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1); 284cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase PropertyValuesHolder pvhScrollX = PropertyValuesHolder.ofInt("scrollX", 0, 1); 285cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase PropertyValuesHolder pvhScrollY = PropertyValuesHolder.ofInt("scrollY", 0, 1); 286622e05c4d2f7c7542ab9cdd30c31813cb6cdb103Chet Haase defaultChangeIn = ObjectAnimator.ofPropertyValuesHolder((Object)null, 287cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScrollX, pvhScrollY); 2882794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase defaultChangeIn.setDuration(DEFAULT_DURATION); 28921cd1389d2ef218b20994b617c57af120841a57fChet Haase defaultChangeIn.setStartDelay(mChangingAppearingDelay); 29021cd1389d2ef218b20994b617c57af120841a57fChet Haase defaultChangeIn.setInterpolator(mChangingAppearingInterpolator); 29121cd1389d2ef218b20994b617c57af120841a57fChet Haase defaultChangeOut = defaultChangeIn.clone(); 29221cd1389d2ef218b20994b617c57af120841a57fChet Haase defaultChangeOut.setStartDelay(mChangingDisappearingDelay); 29321cd1389d2ef218b20994b617c57af120841a57fChet Haase defaultChangeOut.setInterpolator(mChangingDisappearingInterpolator); 2947dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase defaultChange = defaultChangeIn.clone(); 2957dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase defaultChange.setStartDelay(mChangingDelay); 2967dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase defaultChange.setInterpolator(mChangingInterpolator); 297cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 298622e05c4d2f7c7542ab9cdd30c31813cb6cdb103Chet Haase defaultFadeIn = ObjectAnimator.ofFloat(null, "alpha", 0f, 1f); 2992794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase defaultFadeIn.setDuration(DEFAULT_DURATION); 30021cd1389d2ef218b20994b617c57af120841a57fChet Haase defaultFadeIn.setStartDelay(mAppearingDelay); 30121cd1389d2ef218b20994b617c57af120841a57fChet Haase defaultFadeIn.setInterpolator(mAppearingInterpolator); 302622e05c4d2f7c7542ab9cdd30c31813cb6cdb103Chet Haase defaultFadeOut = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f); 3032794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase defaultFadeOut.setDuration(DEFAULT_DURATION); 30421cd1389d2ef218b20994b617c57af120841a57fChet Haase defaultFadeOut.setStartDelay(mDisappearingDelay); 30521cd1389d2ef218b20994b617c57af120841a57fChet Haase defaultFadeOut.setInterpolator(mDisappearingInterpolator); 30621cd1389d2ef218b20994b617c57af120841a57fChet Haase } 30721cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingAppearingAnim = defaultChangeIn; 30821cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingDisappearingAnim = defaultChangeOut; 3097dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mChangingAnim = defaultChange; 31021cd1389d2ef218b20994b617c57af120841a57fChet Haase mAppearingAnim = defaultFadeIn; 31121cd1389d2ef218b20994b617c57af120841a57fChet Haase mDisappearingAnim = defaultFadeOut; 31221cd1389d2ef218b20994b617c57af120841a57fChet Haase } 31321cd1389d2ef218b20994b617c57af120841a57fChet Haase 31421cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 31521cd1389d2ef218b20994b617c57af120841a57fChet Haase * Sets the duration to be used by all animations of this transition object. If you want to 31621cd1389d2ef218b20994b617c57af120841a57fChet Haase * set the duration of just one of the animations in particular, use the 31721cd1389d2ef218b20994b617c57af120841a57fChet Haase * {@link #setDuration(int, long)} method. 31821cd1389d2ef218b20994b617c57af120841a57fChet Haase * 31921cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param duration The length of time, in milliseconds, that the transition animations 32021cd1389d2ef218b20994b617c57af120841a57fChet Haase * should last. 32121cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 32221cd1389d2ef218b20994b617c57af120841a57fChet Haase public void setDuration(long duration) { 32321cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingAppearingDuration = duration; 32421cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingDisappearingDuration = duration; 3257dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mChangingDuration = duration; 32621cd1389d2ef218b20994b617c57af120841a57fChet Haase mAppearingDuration = duration; 32721cd1389d2ef218b20994b617c57af120841a57fChet Haase mDisappearingDuration = duration; 32821cd1389d2ef218b20994b617c57af120841a57fChet Haase } 32921cd1389d2ef218b20994b617c57af120841a57fChet Haase 33021cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 3317dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * Enables the specified transitionType for this LayoutTransition object. 3327dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * By default, a LayoutTransition listens for changes in children being 3337dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * added/remove/hidden/shown in the container, and runs the animations associated with 3347dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * those events. That is, all transition types besides {@link #CHANGING} are enabled by default. 3357dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * You can also enable {@link #CHANGING} animations by calling this method with the 3367dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING} transitionType. 3377dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * 3387dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType One of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, 3397dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}, {@link #APPEARING}, or {@link #DISAPPEARING}. 3407dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase */ 3417dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase public void enableTransitionType(int transitionType) { 3427dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase switch (transitionType) { 3437dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case APPEARING: 3447dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mTransitionTypes |= FLAG_APPEARING; 3457dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 3467dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case DISAPPEARING: 3477dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mTransitionTypes |= FLAG_DISAPPEARING; 3487dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 3497dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGE_APPEARING: 3507dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mTransitionTypes |= FLAG_CHANGE_APPEARING; 3517dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 3527dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGE_DISAPPEARING: 3537dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mTransitionTypes |= FLAG_CHANGE_DISAPPEARING; 3547dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 3557dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 3567dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mTransitionTypes |= FLAG_CHANGING; 3577dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 3587dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 3597dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 3607dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase 3617dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase /** 3627dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * Disables the specified transitionType for this LayoutTransition object. 3637dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * By default, all transition types except {@link #CHANGING} are enabled. 3647dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * 3657dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType One of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, 3667dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}, {@link #APPEARING}, or {@link #DISAPPEARING}. 3677dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase */ 3687dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase public void disableTransitionType(int transitionType) { 3697dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase switch (transitionType) { 3707dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case APPEARING: 3717dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mTransitionTypes &= ~FLAG_APPEARING; 3727dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 3737dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case DISAPPEARING: 3747dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mTransitionTypes &= ~FLAG_DISAPPEARING; 3757dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 3767dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGE_APPEARING: 3777dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mTransitionTypes &= ~FLAG_CHANGE_APPEARING; 3787dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 3797dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGE_DISAPPEARING: 3807dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mTransitionTypes &= ~FLAG_CHANGE_DISAPPEARING; 3817dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 3827dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 3837dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mTransitionTypes &= ~FLAG_CHANGING; 3847dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 3857dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 3867dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 3877dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase 3887dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase /** 3897dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * Returns whether the specified transitionType is enabled for this LayoutTransition object. 3907dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * By default, all transition types except {@link #CHANGING} are enabled. 3917dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * 3927dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType One of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, 3937dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}, {@link #APPEARING}, or {@link #DISAPPEARING}. 3947dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @return true if the specified transitionType is currently enabled, false otherwise. 3957dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase */ 3967dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase public boolean isTransitionTypeEnabled(int transitionType) { 3977dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase switch (transitionType) { 3987dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case APPEARING: 3997dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase return (mTransitionTypes & FLAG_APPEARING) == FLAG_APPEARING; 4007dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case DISAPPEARING: 4017dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase return (mTransitionTypes & FLAG_DISAPPEARING) == FLAG_DISAPPEARING; 4027dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGE_APPEARING: 4037dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase return (mTransitionTypes & FLAG_CHANGE_APPEARING) == FLAG_CHANGE_APPEARING; 4047dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGE_DISAPPEARING: 4057dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase return (mTransitionTypes & FLAG_CHANGE_DISAPPEARING) == FLAG_CHANGE_DISAPPEARING; 4067dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 4077dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase return (mTransitionTypes & FLAG_CHANGING) == FLAG_CHANGING; 4087dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 4097dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase return false; 4107dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 4117dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase 4127dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase /** 41321cd1389d2ef218b20994b617c57af120841a57fChet Haase * Sets the start delay on one of the animation objects used by this transition. The 41421cd1389d2ef218b20994b617c57af120841a57fChet Haase * <code>transitionType</code> parameter determines the animation whose start delay 41521cd1389d2ef218b20994b617c57af120841a57fChet Haase * is being set. 41621cd1389d2ef218b20994b617c57af120841a57fChet Haase * 4177dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType One of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, 4187dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}, {@link #APPEARING}, or {@link #DISAPPEARING}, which determines 4197dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * the animation whose start delay is being set. 42021cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param delay The length of time, in milliseconds, to delay before starting the animation. 421a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @see Animator#setStartDelay(long) 42221cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 42321cd1389d2ef218b20994b617c57af120841a57fChet Haase public void setStartDelay(int transitionType, long delay) { 42421cd1389d2ef218b20994b617c57af120841a57fChet Haase switch (transitionType) { 42521cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_APPEARING: 42621cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingAppearingDelay = delay; 42721cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 42821cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_DISAPPEARING: 42921cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingDisappearingDelay = delay; 43021cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 4317dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 4327dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mChangingDelay = delay; 4337dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 43421cd1389d2ef218b20994b617c57af120841a57fChet Haase case APPEARING: 43521cd1389d2ef218b20994b617c57af120841a57fChet Haase mAppearingDelay = delay; 43621cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 43721cd1389d2ef218b20994b617c57af120841a57fChet Haase case DISAPPEARING: 43821cd1389d2ef218b20994b617c57af120841a57fChet Haase mDisappearingDelay = delay; 43921cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 44021cd1389d2ef218b20994b617c57af120841a57fChet Haase } 44121cd1389d2ef218b20994b617c57af120841a57fChet Haase } 44221cd1389d2ef218b20994b617c57af120841a57fChet Haase 44321cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 44421cd1389d2ef218b20994b617c57af120841a57fChet Haase * Gets the start delay on one of the animation objects used by this transition. The 44521cd1389d2ef218b20994b617c57af120841a57fChet Haase * <code>transitionType</code> parameter determines the animation whose start delay 44621cd1389d2ef218b20994b617c57af120841a57fChet Haase * is returned. 44721cd1389d2ef218b20994b617c57af120841a57fChet Haase * 4487dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType One of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, 4497dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}, {@link #APPEARING}, or {@link #DISAPPEARING}, which determines 4507dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * the animation whose start delay is returned. 45121cd1389d2ef218b20994b617c57af120841a57fChet Haase * @return long The start delay of the specified animation. 452a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @see Animator#getStartDelay() 45321cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 45421cd1389d2ef218b20994b617c57af120841a57fChet Haase public long getStartDelay(int transitionType) { 45521cd1389d2ef218b20994b617c57af120841a57fChet Haase switch (transitionType) { 45621cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_APPEARING: 457cf06d7390cf35aec4f54b705ba4dfdb96fb1c01aRajdeep Dua return mChangingAppearingDelay; 45821cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_DISAPPEARING: 459cf06d7390cf35aec4f54b705ba4dfdb96fb1c01aRajdeep Dua return mChangingDisappearingDelay; 4607dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 4617dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase return mChangingDelay; 46221cd1389d2ef218b20994b617c57af120841a57fChet Haase case APPEARING: 463cf06d7390cf35aec4f54b705ba4dfdb96fb1c01aRajdeep Dua return mAppearingDelay; 46421cd1389d2ef218b20994b617c57af120841a57fChet Haase case DISAPPEARING: 465cf06d7390cf35aec4f54b705ba4dfdb96fb1c01aRajdeep Dua return mDisappearingDelay; 46621cd1389d2ef218b20994b617c57af120841a57fChet Haase } 46721cd1389d2ef218b20994b617c57af120841a57fChet Haase // shouldn't reach here 46821cd1389d2ef218b20994b617c57af120841a57fChet Haase return 0; 46921cd1389d2ef218b20994b617c57af120841a57fChet Haase } 47021cd1389d2ef218b20994b617c57af120841a57fChet Haase 47121cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 47221cd1389d2ef218b20994b617c57af120841a57fChet Haase * Sets the duration on one of the animation objects used by this transition. The 47321cd1389d2ef218b20994b617c57af120841a57fChet Haase * <code>transitionType</code> parameter determines the animation whose duration 47421cd1389d2ef218b20994b617c57af120841a57fChet Haase * is being set. 47521cd1389d2ef218b20994b617c57af120841a57fChet Haase * 4767dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType One of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, 4777dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}, {@link #APPEARING}, or {@link #DISAPPEARING}, which determines 4787dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * the animation whose duration is being set. 47921cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param duration The length of time, in milliseconds, that the specified animation should run. 480a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @see Animator#setDuration(long) 48121cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 48221cd1389d2ef218b20994b617c57af120841a57fChet Haase public void setDuration(int transitionType, long duration) { 48321cd1389d2ef218b20994b617c57af120841a57fChet Haase switch (transitionType) { 48421cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_APPEARING: 48521cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingAppearingDuration = duration; 48621cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 48721cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_DISAPPEARING: 48821cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingDisappearingDuration = duration; 48921cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 4907dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 4917dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mChangingDuration = duration; 4927dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 49321cd1389d2ef218b20994b617c57af120841a57fChet Haase case APPEARING: 49421cd1389d2ef218b20994b617c57af120841a57fChet Haase mAppearingDuration = duration; 49521cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 49621cd1389d2ef218b20994b617c57af120841a57fChet Haase case DISAPPEARING: 49721cd1389d2ef218b20994b617c57af120841a57fChet Haase mDisappearingDuration = duration; 49821cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 49921cd1389d2ef218b20994b617c57af120841a57fChet Haase } 50021cd1389d2ef218b20994b617c57af120841a57fChet Haase } 50121cd1389d2ef218b20994b617c57af120841a57fChet Haase 50221cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 50321cd1389d2ef218b20994b617c57af120841a57fChet Haase * Gets the duration on one of the animation objects used by this transition. The 50421cd1389d2ef218b20994b617c57af120841a57fChet Haase * <code>transitionType</code> parameter determines the animation whose duration 50521cd1389d2ef218b20994b617c57af120841a57fChet Haase * is returned. 50621cd1389d2ef218b20994b617c57af120841a57fChet Haase * 5077dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType One of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, 5087dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}, {@link #APPEARING}, or {@link #DISAPPEARING}, which determines 5097dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * the animation whose duration is returned. 51021cd1389d2ef218b20994b617c57af120841a57fChet Haase * @return long The duration of the specified animation. 511a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @see Animator#getDuration() 51221cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 51321cd1389d2ef218b20994b617c57af120841a57fChet Haase public long getDuration(int transitionType) { 51421cd1389d2ef218b20994b617c57af120841a57fChet Haase switch (transitionType) { 51521cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_APPEARING: 51621cd1389d2ef218b20994b617c57af120841a57fChet Haase return mChangingAppearingDuration; 51721cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_DISAPPEARING: 51821cd1389d2ef218b20994b617c57af120841a57fChet Haase return mChangingDisappearingDuration; 5197dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 5207dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase return mChangingDuration; 52121cd1389d2ef218b20994b617c57af120841a57fChet Haase case APPEARING: 52221cd1389d2ef218b20994b617c57af120841a57fChet Haase return mAppearingDuration; 52321cd1389d2ef218b20994b617c57af120841a57fChet Haase case DISAPPEARING: 52421cd1389d2ef218b20994b617c57af120841a57fChet Haase return mDisappearingDuration; 52521cd1389d2ef218b20994b617c57af120841a57fChet Haase } 52621cd1389d2ef218b20994b617c57af120841a57fChet Haase // shouldn't reach here 52721cd1389d2ef218b20994b617c57af120841a57fChet Haase return 0; 52821cd1389d2ef218b20994b617c57af120841a57fChet Haase } 52921cd1389d2ef218b20994b617c57af120841a57fChet Haase 53021cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 53121cd1389d2ef218b20994b617c57af120841a57fChet Haase * Sets the length of time to delay between starting each animation during one of the 5327dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * change animations. 53321cd1389d2ef218b20994b617c57af120841a57fChet Haase * 5347dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType A value of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, or 5357dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}. 53621cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param duration The length of time, in milliseconds, to delay before launching the next 53721cd1389d2ef218b20994b617c57af120841a57fChet Haase * animation in the sequence. 53821cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 53921cd1389d2ef218b20994b617c57af120841a57fChet Haase public void setStagger(int transitionType, long duration) { 54021cd1389d2ef218b20994b617c57af120841a57fChet Haase switch (transitionType) { 54121cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_APPEARING: 54221cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingAppearingStagger = duration; 54321cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 54421cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_DISAPPEARING: 54521cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingDisappearingStagger = duration; 54621cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 5477dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 5487dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mChangingStagger = duration; 5497dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 55021cd1389d2ef218b20994b617c57af120841a57fChet Haase // noop other cases 55121cd1389d2ef218b20994b617c57af120841a57fChet Haase } 55221cd1389d2ef218b20994b617c57af120841a57fChet Haase } 55321cd1389d2ef218b20994b617c57af120841a57fChet Haase 55421cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 5557dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * Gets the length of time to delay between starting each animation during one of the 5567dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * change animations. 55721cd1389d2ef218b20994b617c57af120841a57fChet Haase * 5587dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType A value of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, or 5597dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}. 56021cd1389d2ef218b20994b617c57af120841a57fChet Haase * @return long The length of time, in milliseconds, to delay before launching the next 56121cd1389d2ef218b20994b617c57af120841a57fChet Haase * animation in the sequence. 56221cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 56321cd1389d2ef218b20994b617c57af120841a57fChet Haase public long getStagger(int transitionType) { 56421cd1389d2ef218b20994b617c57af120841a57fChet Haase switch (transitionType) { 56521cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_APPEARING: 56621cd1389d2ef218b20994b617c57af120841a57fChet Haase return mChangingAppearingStagger; 56721cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_DISAPPEARING: 56821cd1389d2ef218b20994b617c57af120841a57fChet Haase return mChangingDisappearingStagger; 5697dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 5707dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase return mChangingStagger; 57121cd1389d2ef218b20994b617c57af120841a57fChet Haase } 57221cd1389d2ef218b20994b617c57af120841a57fChet Haase // shouldn't reach here 57321cd1389d2ef218b20994b617c57af120841a57fChet Haase return 0; 57421cd1389d2ef218b20994b617c57af120841a57fChet Haase } 57521cd1389d2ef218b20994b617c57af120841a57fChet Haase 57621cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 57721cd1389d2ef218b20994b617c57af120841a57fChet Haase * Sets the interpolator on one of the animation objects used by this transition. The 57821cd1389d2ef218b20994b617c57af120841a57fChet Haase * <code>transitionType</code> parameter determines the animation whose interpolator 57921cd1389d2ef218b20994b617c57af120841a57fChet Haase * is being set. 58021cd1389d2ef218b20994b617c57af120841a57fChet Haase * 5817dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType One of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, 5827dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}, {@link #APPEARING}, or {@link #DISAPPEARING}, which determines 5837dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * the animation whose interpolator is being set. 58421cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param interpolator The interpolator that the specified animation should use. 585e0ee2e9f3102c3c14c873a75a7b04e49787e0fb9Chet Haase * @see Animator#setInterpolator(TimeInterpolator) 58621cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 587e0ee2e9f3102c3c14c873a75a7b04e49787e0fb9Chet Haase public void setInterpolator(int transitionType, TimeInterpolator interpolator) { 58821cd1389d2ef218b20994b617c57af120841a57fChet Haase switch (transitionType) { 58921cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_APPEARING: 59021cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingAppearingInterpolator = interpolator; 59121cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 59221cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_DISAPPEARING: 59321cd1389d2ef218b20994b617c57af120841a57fChet Haase mChangingDisappearingInterpolator = interpolator; 59421cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 5957dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 5967dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mChangingInterpolator = interpolator; 5977dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 59821cd1389d2ef218b20994b617c57af120841a57fChet Haase case APPEARING: 59921cd1389d2ef218b20994b617c57af120841a57fChet Haase mAppearingInterpolator = interpolator; 60021cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 60121cd1389d2ef218b20994b617c57af120841a57fChet Haase case DISAPPEARING: 60221cd1389d2ef218b20994b617c57af120841a57fChet Haase mDisappearingInterpolator = interpolator; 60321cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 60421cd1389d2ef218b20994b617c57af120841a57fChet Haase } 60521cd1389d2ef218b20994b617c57af120841a57fChet Haase } 60621cd1389d2ef218b20994b617c57af120841a57fChet Haase 60721cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 60821cd1389d2ef218b20994b617c57af120841a57fChet Haase * Gets the interpolator on one of the animation objects used by this transition. The 60921cd1389d2ef218b20994b617c57af120841a57fChet Haase * <code>transitionType</code> parameter determines the animation whose interpolator 61021cd1389d2ef218b20994b617c57af120841a57fChet Haase * is returned. 61121cd1389d2ef218b20994b617c57af120841a57fChet Haase * 6127dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType One of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, 6137dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}, {@link #APPEARING}, or {@link #DISAPPEARING}, which determines 6147dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * the animation whose interpolator is being returned. 615e0ee2e9f3102c3c14c873a75a7b04e49787e0fb9Chet Haase * @return TimeInterpolator The interpolator that the specified animation uses. 616e0ee2e9f3102c3c14c873a75a7b04e49787e0fb9Chet Haase * @see Animator#setInterpolator(TimeInterpolator) 61721cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 618e0ee2e9f3102c3c14c873a75a7b04e49787e0fb9Chet Haase public TimeInterpolator getInterpolator(int transitionType) { 61921cd1389d2ef218b20994b617c57af120841a57fChet Haase switch (transitionType) { 62021cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_APPEARING: 62121cd1389d2ef218b20994b617c57af120841a57fChet Haase return mChangingAppearingInterpolator; 62221cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_DISAPPEARING: 62321cd1389d2ef218b20994b617c57af120841a57fChet Haase return mChangingDisappearingInterpolator; 6247dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 6257dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase return mChangingInterpolator; 62621cd1389d2ef218b20994b617c57af120841a57fChet Haase case APPEARING: 62721cd1389d2ef218b20994b617c57af120841a57fChet Haase return mAppearingInterpolator; 62821cd1389d2ef218b20994b617c57af120841a57fChet Haase case DISAPPEARING: 62921cd1389d2ef218b20994b617c57af120841a57fChet Haase return mDisappearingInterpolator; 63021cd1389d2ef218b20994b617c57af120841a57fChet Haase } 63121cd1389d2ef218b20994b617c57af120841a57fChet Haase // shouldn't reach here 63221cd1389d2ef218b20994b617c57af120841a57fChet Haase return null; 63321cd1389d2ef218b20994b617c57af120841a57fChet Haase } 63421cd1389d2ef218b20994b617c57af120841a57fChet Haase 63521cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 63621cd1389d2ef218b20994b617c57af120841a57fChet Haase * Sets the animation used during one of the transition types that may run. Any 637a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * Animator object can be used, but to be most useful in the context of layout 638a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * transitions, the animation should either be a ObjectAnimator or a AnimatorSet 639a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * of animations including PropertyAnimators. Also, these ObjectAnimator objects 64021cd1389d2ef218b20994b617c57af120841a57fChet Haase * should be able to get and set values on their target objects automatically. For 641a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * example, a ObjectAnimator that animates the property "left" is able to set and get the 64221cd1389d2ef218b20994b617c57af120841a57fChet Haase * <code>left</code> property from the View objects being animated by the layout 64321cd1389d2ef218b20994b617c57af120841a57fChet Haase * transition. The transition works by setting target objects and properties 64421cd1389d2ef218b20994b617c57af120841a57fChet Haase * dynamically, according to the pre- and post-layoout values of those objects, so 64521cd1389d2ef218b20994b617c57af120841a57fChet Haase * having animations that can handle those properties appropriately will work best 64621cd1389d2ef218b20994b617c57af120841a57fChet Haase * for custom animation. The dynamic setting of values is only the case for the 64721cd1389d2ef218b20994b617c57af120841a57fChet Haase * CHANGE animations; the APPEARING and DISAPPEARING animations are simply run with 64821cd1389d2ef218b20994b617c57af120841a57fChet Haase * the values they have. 64921cd1389d2ef218b20994b617c57af120841a57fChet Haase * 65021cd1389d2ef218b20994b617c57af120841a57fChet Haase * <p>It is also worth noting that any and all animations (and their underlying 65121cd1389d2ef218b20994b617c57af120841a57fChet Haase * PropertyValuesHolder objects) will have their start and end values set according 65221cd1389d2ef218b20994b617c57af120841a57fChet Haase * to the pre- and post-layout values. So, for example, a custom animation on "alpha" 65321cd1389d2ef218b20994b617c57af120841a57fChet Haase * as the CHANGE_APPEARING animation will inherit the real value of alpha on the target 65421cd1389d2ef218b20994b617c57af120841a57fChet Haase * object (presumably 1) as its starting and ending value when the animation begins. 65521cd1389d2ef218b20994b617c57af120841a57fChet Haase * Animations which need to use values at the beginning and end that may not match the 65621cd1389d2ef218b20994b617c57af120841a57fChet Haase * values queried when the transition begins may need to use a different mechanism 657a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * than a standard ObjectAnimator object.</p> 65821cd1389d2ef218b20994b617c57af120841a57fChet Haase * 6597dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType One of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, 6607dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}, {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the 6617dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * animation whose animator is being set. 6625d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase * @param animator The animation being assigned. A value of <code>null</code> means that no 6635d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase * animation will be run for the specified transitionType. 66421cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 665a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public void setAnimator(int transitionType, Animator animator) { 66621cd1389d2ef218b20994b617c57af120841a57fChet Haase switch (transitionType) { 66721cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_APPEARING: 6685d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase mChangingAppearingAnim = animator; 66921cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 67021cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_DISAPPEARING: 6715d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase mChangingDisappearingAnim = animator; 67221cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 6737dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 6747dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase mChangingAnim = animator; 6757dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 67621cd1389d2ef218b20994b617c57af120841a57fChet Haase case APPEARING: 6775d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase mAppearingAnim = animator; 67821cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 67921cd1389d2ef218b20994b617c57af120841a57fChet Haase case DISAPPEARING: 6805d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase mDisappearingAnim = animator; 68121cd1389d2ef218b20994b617c57af120841a57fChet Haase break; 68221cd1389d2ef218b20994b617c57af120841a57fChet Haase } 68321cd1389d2ef218b20994b617c57af120841a57fChet Haase } 68421cd1389d2ef218b20994b617c57af120841a57fChet Haase 68521cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 68621cd1389d2ef218b20994b617c57af120841a57fChet Haase * Gets the animation used during one of the transition types that may run. 68721cd1389d2ef218b20994b617c57af120841a57fChet Haase * 6887dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param transitionType One of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, 6897dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * {@link #CHANGING}, {@link #APPEARING}, or {@link #DISAPPEARING}, which determines 6907dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * the animation whose animator is being returned. 691a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @return Animator The animation being used for the given transition type. 692a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase * @see #setAnimator(int, Animator) 69321cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 694a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase public Animator getAnimator(int transitionType) { 69521cd1389d2ef218b20994b617c57af120841a57fChet Haase switch (transitionType) { 69621cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_APPEARING: 69721cd1389d2ef218b20994b617c57af120841a57fChet Haase return mChangingAppearingAnim; 69821cd1389d2ef218b20994b617c57af120841a57fChet Haase case CHANGE_DISAPPEARING: 69921cd1389d2ef218b20994b617c57af120841a57fChet Haase return mChangingDisappearingAnim; 7007dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 7017dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase return mChangingAnim; 70221cd1389d2ef218b20994b617c57af120841a57fChet Haase case APPEARING: 70321cd1389d2ef218b20994b617c57af120841a57fChet Haase return mAppearingAnim; 70421cd1389d2ef218b20994b617c57af120841a57fChet Haase case DISAPPEARING: 70521cd1389d2ef218b20994b617c57af120841a57fChet Haase return mDisappearingAnim; 70621cd1389d2ef218b20994b617c57af120841a57fChet Haase } 70721cd1389d2ef218b20994b617c57af120841a57fChet Haase // shouldn't reach here 70821cd1389d2ef218b20994b617c57af120841a57fChet Haase return null; 70921cd1389d2ef218b20994b617c57af120841a57fChet Haase } 71021cd1389d2ef218b20994b617c57af120841a57fChet Haase 71121cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 712eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase * This function sets up animations on all of the views that change during layout. 71321cd1389d2ef218b20994b617c57af120841a57fChet Haase * For every child in the parent, we create a change animation of the appropriate 7147dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * type (appearing, disappearing, or changing) and ask it to populate its start values from its 71521cd1389d2ef218b20994b617c57af120841a57fChet Haase * target view. We add layout listeners to all child views and listen for changes. For 71621cd1389d2ef218b20994b617c57af120841a57fChet Haase * those views that change, we populate the end values for those animations and start them. 71721cd1389d2ef218b20994b617c57af120841a57fChet Haase * Animations are not run on unchanging views. 71821cd1389d2ef218b20994b617c57af120841a57fChet Haase * 7197dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param parent The container which is undergoing a change. 7207dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param newView The view being added to or removed from the parent. May be null if the 7217dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * changeReason is CHANGING. 7227dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param changeReason A value of APPEARING, DISAPPEARING, or CHANGING, indicating whether the 7237dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * transition is occurring because an item is being added to or removed from the parent, or 7247dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * if it is running in response to a layout operation (that is, if the value is CHANGING). 72521cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 72621cd1389d2ef218b20994b617c57af120841a57fChet Haase private void runChangeTransition(final ViewGroup parent, View newView, final int changeReason) { 7275d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase 7287dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase Animator baseAnimator = null; 7297dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase Animator parentAnimator = null; 7307dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase final long duration; 7317dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase switch (changeReason) { 7327dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case APPEARING: 7337dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase baseAnimator = mChangingAppearingAnim; 7347dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase duration = mChangingAppearingDuration; 7357dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase parentAnimator = defaultChangeIn; 7367dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 7377dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case DISAPPEARING: 7387dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase baseAnimator = mChangingDisappearingAnim; 7397dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase duration = mChangingDisappearingDuration; 7407dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase parentAnimator = defaultChangeOut; 7417dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 7427dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 7437dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase baseAnimator = mChangingAnim; 7447dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase duration = mChangingDuration; 7457dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase parentAnimator = defaultChange; 7467dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 7477dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase default: 7487dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase // Shouldn't reach here 7497dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase duration = 0; 7507dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 7517dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 7525d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase // If the animation is null, there's nothing to do 7535d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase if (baseAnimator == null) { 7545d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase return; 7555d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase } 7565d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase 75721cd1389d2ef218b20994b617c57af120841a57fChet Haase // reset the inter-animation delay, in case we use it later 75821cd1389d2ef218b20994b617c57af120841a57fChet Haase staggerDelay = 0; 75921cd1389d2ef218b20994b617c57af120841a57fChet Haase 76021cd1389d2ef218b20994b617c57af120841a57fChet Haase final ViewTreeObserver observer = parent.getViewTreeObserver(); // used for later cleanup 761634a20acf713ffe0d4a67c0b888cf1e9782890e7Chet Haase if (!observer.isAlive()) { 762634a20acf713ffe0d4a67c0b888cf1e9782890e7Chet Haase // If the observer's not in a good state, skip the transition 763634a20acf713ffe0d4a67c0b888cf1e9782890e7Chet Haase return; 764634a20acf713ffe0d4a67c0b888cf1e9782890e7Chet Haase } 76521cd1389d2ef218b20994b617c57af120841a57fChet Haase int numChildren = parent.getChildCount(); 76621cd1389d2ef218b20994b617c57af120841a57fChet Haase 76721cd1389d2ef218b20994b617c57af120841a57fChet Haase for (int i = 0; i < numChildren; ++i) { 76821cd1389d2ef218b20994b617c57af120841a57fChet Haase final View child = parent.getChildAt(i); 76921cd1389d2ef218b20994b617c57af120841a57fChet Haase 77021cd1389d2ef218b20994b617c57af120841a57fChet Haase // only animate the views not being added or removed 77121cd1389d2ef218b20994b617c57af120841a57fChet Haase if (child != newView) { 772cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase setupChangeAnimation(parent, changeReason, baseAnimator, duration, child); 773cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 774cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 775cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase if (mAnimateParentHierarchy) { 776cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase ViewGroup tempParent = parent; 777cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase while (tempParent != null) { 778cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase ViewParent parentParent = tempParent.getParent(); 779cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase if (parentParent instanceof ViewGroup) { 780e115ffeb3a05f440c0062ad9b3954b7fefef4b00Chet Haase setupChangeAnimation((ViewGroup)parentParent, changeReason, parentAnimator, 781cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase duration, tempParent); 782cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase tempParent = (ViewGroup) parentParent; 783cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } else { 784cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase tempParent = null; 7850dfc39842459daea98e2b551bbecd16d1baca439Chet Haase } 78621cd1389d2ef218b20994b617c57af120841a57fChet Haase 78721cd1389d2ef218b20994b617c57af120841a57fChet Haase } 78821cd1389d2ef218b20994b617c57af120841a57fChet Haase } 789cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 79021cd1389d2ef218b20994b617c57af120841a57fChet Haase // This is the cleanup step. When we get this rendering event, we know that all of 79121cd1389d2ef218b20994b617c57af120841a57fChet Haase // the appropriate animations have been set up and run. Now we can clear out the 79221cd1389d2ef218b20994b617c57af120841a57fChet Haase // layout listeners. 79321cd1389d2ef218b20994b617c57af120841a57fChet Haase observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 79421cd1389d2ef218b20994b617c57af120841a57fChet Haase public boolean onPreDraw() { 795634a20acf713ffe0d4a67c0b888cf1e9782890e7Chet Haase parent.getViewTreeObserver().removeOnPreDrawListener(this); 7961a76dcd6d1e30f92668b5df309398d545cef9aceChet Haase int count = layoutChangeListenerMap.size(); 7971a76dcd6d1e30f92668b5df309398d545cef9aceChet Haase if (count > 0) { 7981a76dcd6d1e30f92668b5df309398d545cef9aceChet Haase Collection<View> views = layoutChangeListenerMap.keySet(); 7991a76dcd6d1e30f92668b5df309398d545cef9aceChet Haase for (View view : views) { 8001a76dcd6d1e30f92668b5df309398d545cef9aceChet Haase View.OnLayoutChangeListener listener = layoutChangeListenerMap.get(view); 8011a76dcd6d1e30f92668b5df309398d545cef9aceChet Haase view.removeOnLayoutChangeListener(listener); 8021a76dcd6d1e30f92668b5df309398d545cef9aceChet Haase } 80321cd1389d2ef218b20994b617c57af120841a57fChet Haase } 80421cd1389d2ef218b20994b617c57af120841a57fChet Haase layoutChangeListenerMap.clear(); 80521cd1389d2ef218b20994b617c57af120841a57fChet Haase return true; 80621cd1389d2ef218b20994b617c57af120841a57fChet Haase } 80721cd1389d2ef218b20994b617c57af120841a57fChet Haase }); 80821cd1389d2ef218b20994b617c57af120841a57fChet Haase } 80921cd1389d2ef218b20994b617c57af120841a57fChet Haase 81021cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 811cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * This flag controls whether CHANGE_APPEARING or CHANGE_DISAPPEARING animations will 812e115ffeb3a05f440c0062ad9b3954b7fefef4b00Chet Haase * cause the default changing animation to be run on the parent hierarchy as well. This allows 813cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * containers of transitioning views to also transition, which may be necessary in situations 814cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * where the containers bounds change between the before/after states and may clip their 815cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * children during the transition animations. For example, layouts with wrap_content will 816cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * adjust their bounds according to the dimensions of their children. 817cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * 818e115ffeb3a05f440c0062ad9b3954b7fefef4b00Chet Haase * <p>The default changing transitions animate the bounds and scroll positions of the 819e115ffeb3a05f440c0062ad9b3954b7fefef4b00Chet Haase * target views. These are the animations that will run on the parent hierarchy, not 820e115ffeb3a05f440c0062ad9b3954b7fefef4b00Chet Haase * the custom animations that happen to be set on the transition. This allows custom 821e115ffeb3a05f440c0062ad9b3954b7fefef4b00Chet Haase * behavior for the children of the transitioning container, but uses standard behavior 822e115ffeb3a05f440c0062ad9b3954b7fefef4b00Chet Haase * of resizing/rescrolling on any changing parents. 823e115ffeb3a05f440c0062ad9b3954b7fefef4b00Chet Haase * 824cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * @param animateParentHierarchy A boolean value indicating whether the parents of 825cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * transitioning views should also be animated during the transition. Default value is true. 826cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase */ 827cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase public void setAnimateParentHierarchy(boolean animateParentHierarchy) { 828cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase mAnimateParentHierarchy = animateParentHierarchy; 829cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 830cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 831cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase /** 832cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * Utility function called by runChangingTransition for both the children and the parent 833cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * hierarchy. 834cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase */ 835cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase private void setupChangeAnimation(final ViewGroup parent, final int changeReason, 836cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase Animator baseAnimator, final long duration, final View child) { 8378a22e59311ab797aeb10682b4c9e036ded95a429Chet Haase 8388a22e59311ab797aeb10682b4c9e036ded95a429Chet Haase // If we already have a listener for this child, then we've already set up the 8398a22e59311ab797aeb10682b4c9e036ded95a429Chet Haase // changing animation we need. Multiple calls for a child may occur when several 8408a22e59311ab797aeb10682b4c9e036ded95a429Chet Haase // add/remove operations are run at once on a container; each one will trigger 8418a22e59311ab797aeb10682b4c9e036ded95a429Chet Haase // changes for the existing children in the container. 8428a22e59311ab797aeb10682b4c9e036ded95a429Chet Haase if (layoutChangeListenerMap.get(child) != null) { 8438a22e59311ab797aeb10682b4c9e036ded95a429Chet Haase return; 8448a22e59311ab797aeb10682b4c9e036ded95a429Chet Haase } 8458a22e59311ab797aeb10682b4c9e036ded95a429Chet Haase 84666ef1a201ea9df71a8ec9b2d1aaab1eb1180ae40Chet Haase // Don't animate items up from size(0,0); this is likely because the objects 84766ef1a201ea9df71a8ec9b2d1aaab1eb1180ae40Chet Haase // were offscreen/invisible or otherwise measured to be infinitely small. We don't 84866ef1a201ea9df71a8ec9b2d1aaab1eb1180ae40Chet Haase // want to see them animate into their real size; just ignore animation requests 84966ef1a201ea9df71a8ec9b2d1aaab1eb1180ae40Chet Haase // on these views 85066ef1a201ea9df71a8ec9b2d1aaab1eb1180ae40Chet Haase if (child.getWidth() == 0 && child.getHeight() == 0) { 85166ef1a201ea9df71a8ec9b2d1aaab1eb1180ae40Chet Haase return; 85266ef1a201ea9df71a8ec9b2d1aaab1eb1180ae40Chet Haase } 85366ef1a201ea9df71a8ec9b2d1aaab1eb1180ae40Chet Haase 854cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // Make a copy of the appropriate animation 855cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase final Animator anim = baseAnimator.clone(); 856cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 857cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // Set the target object for the animation 858cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase anim.setTarget(child); 859cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 860cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // A ObjectAnimator (or AnimatorSet of them) can extract start values from 861cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // its target object 862cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase anim.setupStartValues(); 863cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 864cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // If there's an animation running on this view already, cancel it 865cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase Animator currentAnimation = pendingAnimations.get(child); 866cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase if (currentAnimation != null) { 867cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase currentAnimation.cancel(); 868cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase pendingAnimations.remove(child); 869cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 870cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // Cache the animation in case we need to cancel it later 871cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase pendingAnimations.put(child, anim); 872cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 873cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // For the animations which don't get started, we have to have a means of 874cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // removing them from the cache, lest we leak them and their target objects. 875cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // We run an animator for the default duration+100 (an arbitrary time, but one 876cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // which should far surpass the delay between setting them up here and 877cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // handling layout events which start them. 878cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase ValueAnimator pendingAnimRemover = ValueAnimator.ofFloat(0f, 1f). 879cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase setDuration(duration + 100); 880cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase pendingAnimRemover.addListener(new AnimatorListenerAdapter() { 881cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase @Override 882cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase public void onAnimationEnd(Animator animation) { 883cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase pendingAnimations.remove(child); 884cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 885cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase }); 886cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase pendingAnimRemover.start(); 887cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 888cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // Add a listener to track layout changes on this view. If we don't get a callback, 889cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // then there's nothing to animate. 890cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase final View.OnLayoutChangeListener listener = new View.OnLayoutChangeListener() { 891cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase public void onLayoutChange(View v, int left, int top, int right, int bottom, 892cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase int oldLeft, int oldTop, int oldRight, int oldBottom) { 893cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 894cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // Tell the animation to extract end values from the changed object 895cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase anim.setupEndValues(); 896cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase if (anim instanceof ValueAnimator) { 897cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase boolean valuesDiffer = false; 898cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase ValueAnimator valueAnim = (ValueAnimator)anim; 899cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase PropertyValuesHolder[] oldValues = valueAnim.getValues(); 900cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase for (int i = 0; i < oldValues.length; ++i) { 901cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase PropertyValuesHolder pvh = oldValues[i]; 902cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase KeyframeSet keyframeSet = pvh.mKeyframeSet; 903cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase if (keyframeSet.mFirstKeyframe == null || 904cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase keyframeSet.mLastKeyframe == null || 905cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase !keyframeSet.mFirstKeyframe.getValue().equals( 906cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase keyframeSet.mLastKeyframe.getValue())) { 907cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase valuesDiffer = true; 908cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 909cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 910cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase if (!valuesDiffer) { 911cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase return; 912cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 913cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 914cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 9157dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase long startDelay = 0; 9167dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase switch (changeReason) { 9177dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case APPEARING: 9187dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase startDelay = mChangingAppearingDelay + staggerDelay; 9197dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase staggerDelay += mChangingAppearingStagger; 92033d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase if (mChangingAppearingInterpolator != sChangingAppearingInterpolator) { 92133d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase anim.setInterpolator(mChangingAppearingInterpolator); 92233d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase } 9237dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 9247dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case DISAPPEARING: 9257dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase startDelay = mChangingDisappearingDelay + staggerDelay; 9267dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase staggerDelay += mChangingDisappearingStagger; 92733d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase if (mChangingDisappearingInterpolator != 92833d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase sChangingDisappearingInterpolator) { 92933d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase anim.setInterpolator(mChangingDisappearingInterpolator); 93033d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase } 9317dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 9327dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 9337dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase startDelay = mChangingDelay + staggerDelay; 9347dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase staggerDelay += mChangingStagger; 93533d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase if (mChangingInterpolator != sChangingInterpolator) { 93633d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase anim.setInterpolator(mChangingInterpolator); 93733d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase } 9387dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase break; 939cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 940cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase anim.setStartDelay(startDelay); 941cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase anim.setDuration(duration); 942cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 943cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase Animator prevAnimation = currentChangingAnimations.get(child); 944cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase if (prevAnimation != null) { 945cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase prevAnimation.cancel(); 946cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 947cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase Animator pendingAnimation = pendingAnimations.get(child); 948cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase if (pendingAnimation != null) { 949cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase pendingAnimations.remove(child); 950cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 951cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // Cache the animation in case we need to cancel it later 952cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase currentChangingAnimations.put(child, anim); 953cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 954cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase parent.requestTransitionStart(LayoutTransition.this); 955cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 956cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // this only removes listeners whose views changed - must clear the 957cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // other listeners later 958cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase child.removeOnLayoutChangeListener(this); 959cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase layoutChangeListenerMap.remove(child); 960cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 961cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase }; 962cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // Remove the animation from the cache when it ends 963cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase anim.addListener(new AnimatorListenerAdapter() { 964cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 965cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase @Override 966cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase public void onAnimationStart(Animator animator) { 967c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin if (hasListeners()) { 968c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin ArrayList<TransitionListener> listeners = 969c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin (ArrayList<TransitionListener>) mListeners.clone(); 970c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin for (TransitionListener listener : listeners) { 971cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase listener.startTransition(LayoutTransition.this, parent, child, 972cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase changeReason == APPEARING ? 9737dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase CHANGE_APPEARING : changeReason == DISAPPEARING ? 9747dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase CHANGE_DISAPPEARING : CHANGING); 975cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 976cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 977cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 978cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 979cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase @Override 980cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase public void onAnimationCancel(Animator animator) { 981cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase child.removeOnLayoutChangeListener(listener); 982cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase layoutChangeListenerMap.remove(child); 983cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 984cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 985cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase @Override 986cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase public void onAnimationEnd(Animator animator) { 987cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase currentChangingAnimations.remove(child); 988c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin if (hasListeners()) { 989c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin ArrayList<TransitionListener> listeners = 990c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin (ArrayList<TransitionListener>) mListeners.clone(); 991c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin for (TransitionListener listener : listeners) { 992cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase listener.endTransition(LayoutTransition.this, parent, child, 993cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase changeReason == APPEARING ? 9947dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase CHANGE_APPEARING : changeReason == DISAPPEARING ? 9957dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase CHANGE_DISAPPEARING : CHANGING); 996cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 997cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 998cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 999cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase }); 1000cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 1001cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase child.addOnLayoutChangeListener(listener); 1002cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase // cache the listener for later removal 1003cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase layoutChangeListenerMap.put(child, listener); 1004cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 1005cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 1006cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase /** 1007cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * Starts the animations set up for a CHANGING transition. We separate the setup of these 1008cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * animations from actually starting them, to avoid side-effects that starting the animations 1009cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * may have on the properties of the affected objects. After setup, we tell the affected parent 1010cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * that this transition should be started. The parent informs its ViewAncestor, which then 1011cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * starts the transition after the current layout/measurement phase, just prior to drawing 1012cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * the view hierarchy. 1013cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * 1014cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase * @hide 1015cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase */ 1016cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase public void startChangingAnimations() { 1017d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase LinkedHashMap<View, Animator> currentAnimCopy = 1018d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase (LinkedHashMap<View, Animator>) currentChangingAnimations.clone(); 1019d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase for (Animator anim : currentAnimCopy.values()) { 1020cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase if (anim instanceof ObjectAnimator) { 1021cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase ((ObjectAnimator) anim).setCurrentPlayTime(0); 1022cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 1023cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase anim.start(); 1024cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 1025cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase } 1026cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase 1027cca2c9807206f320bd41bf8656a227e4f249e4baChet Haase /** 1028d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase * Ends the animations that are set up for a CHANGING transition. This is a variant of 1029d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase * startChangingAnimations() which is called when the window the transition is playing in 1030d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase * is not visible. We need to make sure the animations put their targets in their end states 1031d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase * and that the transition finishes to remove any mid-process state (such as isRunning()). 1032d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase * 1033d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase * @hide 1034d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase */ 1035d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase public void endChangingAnimations() { 1036d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase LinkedHashMap<View, Animator> currentAnimCopy = 1037d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase (LinkedHashMap<View, Animator>) currentChangingAnimations.clone(); 1038d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase for (Animator anim : currentAnimCopy.values()) { 1039d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase anim.start(); 1040d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase anim.end(); 1041d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase } 104217cf42cb85c22b50ecfa8d21efc992f99d20fc45Chet Haase // listeners should clean up the currentChangingAnimations list, but just in case... 104317cf42cb85c22b50ecfa8d21efc992f99d20fc45Chet Haase currentChangingAnimations.clear(); 1044d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase } 1045d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase 1046d56c6951755a902a354e13e5fa05fb0984132cc6Chet Haase /** 10479c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * Returns true if animations are running which animate layout-related properties. This 10489c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * essentially means that either CHANGE_APPEARING or CHANGE_DISAPPEARING animations 10499c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * are running, since these animations operate on layout-related properties. 10509c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * 10519c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * @return true if CHANGE_APPEARING or CHANGE_DISAPPEARING animations are currently 10529c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * running. 10539c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase */ 10549c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase public boolean isChangingLayout() { 10559c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase return (currentChangingAnimations.size() > 0); 10569c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase } 10579c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase 10589c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase /** 10599c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * Returns true if any of the animations in this transition are currently running. 10609c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * 10619c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * @return true if any animations in the transition are running. 10629c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase */ 10639c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase public boolean isRunning() { 1064e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase return (currentChangingAnimations.size() > 0 || currentAppearingAnimations.size() > 0 || 1065e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase currentDisappearingAnimations.size() > 0); 10669c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase } 10679c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase 10689c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase /** 1069add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase * Cancels the currently running transition. Note that we cancel() the changing animations 1070add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase * but end() the visibility animations. This is because this method is currently called 1071add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase * in the context of starting a new transition, so we want to move things from their mid- 1072add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase * transition positions, but we want them to have their end-transition visibility. 1073add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase * 1074add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase * @hide 1075add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase */ 1076add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase public void cancel() { 1077e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase if (currentChangingAnimations.size() > 0) { 1078eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase LinkedHashMap<View, Animator> currentAnimCopy = 1079eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase (LinkedHashMap<View, Animator>) currentChangingAnimations.clone(); 1080e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase for (Animator anim : currentAnimCopy.values()) { 1081e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase anim.cancel(); 1082e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1083e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase currentChangingAnimations.clear(); 1084e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1085e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase if (currentAppearingAnimations.size() > 0) { 1086eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase LinkedHashMap<View, Animator> currentAnimCopy = 1087eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase (LinkedHashMap<View, Animator>) currentAppearingAnimations.clone(); 1088e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase for (Animator anim : currentAnimCopy.values()) { 1089e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase anim.end(); 1090e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1091e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase currentAppearingAnimations.clear(); 1092add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase } 1093e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase if (currentDisappearingAnimations.size() > 0) { 1094eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase LinkedHashMap<View, Animator> currentAnimCopy = 1095eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase (LinkedHashMap<View, Animator>) currentDisappearingAnimations.clone(); 1096e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase for (Animator anim : currentAnimCopy.values()) { 1097e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase anim.end(); 1098e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1099e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase currentDisappearingAnimations.clear(); 1100e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1101e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1102e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase 1103e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase /** 1104e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase * Cancels the specified type of transition. Note that we cancel() the changing animations 1105e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase * but end() the visibility animations. This is because this method is currently called 1106e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase * in the context of starting a new transition, so we want to move things from their mid- 1107e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase * transition positions, but we want them to have their end-transition visibility. 1108e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase * 1109e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase * @hide 1110e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase */ 1111e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase public void cancel(int transitionType) { 1112e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase switch (transitionType) { 1113e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase case CHANGE_APPEARING: 1114e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase case CHANGE_DISAPPEARING: 11157dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase case CHANGING: 1116e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase if (currentChangingAnimations.size() > 0) { 1117eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase LinkedHashMap<View, Animator> currentAnimCopy = 1118eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase (LinkedHashMap<View, Animator>) currentChangingAnimations.clone(); 1119e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase for (Animator anim : currentAnimCopy.values()) { 1120e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase anim.cancel(); 1121e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1122e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase currentChangingAnimations.clear(); 1123e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1124e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase break; 1125e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase case APPEARING: 1126e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase if (currentAppearingAnimations.size() > 0) { 1127eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase LinkedHashMap<View, Animator> currentAnimCopy = 1128eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase (LinkedHashMap<View, Animator>) currentAppearingAnimations.clone(); 1129e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase for (Animator anim : currentAnimCopy.values()) { 1130e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase anim.end(); 1131e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1132e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase currentAppearingAnimations.clear(); 1133e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1134e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase break; 1135e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase case DISAPPEARING: 1136e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase if (currentDisappearingAnimations.size() > 0) { 1137eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase LinkedHashMap<View, Animator> currentAnimCopy = 1138eb1d851e0e6c2dc1de0ec7990ccf7d29dda41a9aChet Haase (LinkedHashMap<View, Animator>) currentDisappearingAnimations.clone(); 1139e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase for (Animator anim : currentAnimCopy.values()) { 1140e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase anim.end(); 1141e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1142e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase currentDisappearingAnimations.clear(); 1143e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase } 1144e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase break; 1145add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase } 1146add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase } 1147add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase 1148add6577a0196258e5a48c5deefcdb12e05c935b3Chet Haase /** 114921cd1389d2ef218b20994b617c57af120841a57fChet Haase * This method runs the animation that makes an added item appear. 115021cd1389d2ef218b20994b617c57af120841a57fChet Haase * 115121cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param parent The ViewGroup to which the View is being added. 115221cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param child The View being added to the ViewGroup. 115321cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 115421cd1389d2ef218b20994b617c57af120841a57fChet Haase private void runAppearingTransition(final ViewGroup parent, final View child) { 1155e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase Animator currentAnimation = currentDisappearingAnimations.get(child); 1156e64ea87f966e995f5e1a77f991b9da0ed21ffab0Chet Haase if (currentAnimation != null) { 1157e64ea87f966e995f5e1a77f991b9da0ed21ffab0Chet Haase currentAnimation.cancel(); 1158e64ea87f966e995f5e1a77f991b9da0ed21ffab0Chet Haase } 11595d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase if (mAppearingAnim == null) { 1160c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin if (hasListeners()) { 1161c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin ArrayList<TransitionListener> listeners = 1162c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin (ArrayList<TransitionListener>) mListeners.clone(); 1163c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin for (TransitionListener listener : listeners) { 11645d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase listener.endTransition(LayoutTransition.this, parent, child, APPEARING); 11655d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase } 11665d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase } 11675d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase return; 11685d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase } 1169a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase Animator anim = mAppearingAnim.clone(); 117021cd1389d2ef218b20994b617c57af120841a57fChet Haase anim.setTarget(child); 117121cd1389d2ef218b20994b617c57af120841a57fChet Haase anim.setStartDelay(mAppearingDelay); 117221cd1389d2ef218b20994b617c57af120841a57fChet Haase anim.setDuration(mAppearingDuration); 117333d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase if (mAppearingInterpolator != sAppearingInterpolator) { 117433d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase anim.setInterpolator(mAppearingInterpolator); 117533d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase } 1176a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (anim instanceof ObjectAnimator) { 1177a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ((ObjectAnimator) anim).setCurrentPlayTime(0); 117821cd1389d2ef218b20994b617c57af120841a57fChet Haase } 1179a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase anim.addListener(new AnimatorListenerAdapter() { 1180a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase @Override 1181a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase public void onAnimationEnd(Animator anim) { 1182a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase currentAppearingAnimations.remove(child); 1183c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin if (hasListeners()) { 1184c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin ArrayList<TransitionListener> listeners = 1185c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin (ArrayList<TransitionListener>) mListeners.clone(); 1186c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin for (TransitionListener listener : listeners) { 118721cd1389d2ef218b20994b617c57af120841a57fChet Haase listener.endTransition(LayoutTransition.this, parent, child, APPEARING); 118821cd1389d2ef218b20994b617c57af120841a57fChet Haase } 118921cd1389d2ef218b20994b617c57af120841a57fChet Haase } 1190a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase } 1191a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase }); 1192e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase currentAppearingAnimations.put(child, anim); 119321cd1389d2ef218b20994b617c57af120841a57fChet Haase anim.start(); 119421cd1389d2ef218b20994b617c57af120841a57fChet Haase } 119521cd1389d2ef218b20994b617c57af120841a57fChet Haase 119621cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 119721cd1389d2ef218b20994b617c57af120841a57fChet Haase * This method runs the animation that makes a removed item disappear. 119821cd1389d2ef218b20994b617c57af120841a57fChet Haase * 119921cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param parent The ViewGroup from which the View is being removed. 120021cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param child The View being removed from the ViewGroup. 120121cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 120221cd1389d2ef218b20994b617c57af120841a57fChet Haase private void runDisappearingTransition(final ViewGroup parent, final View child) { 1203e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase Animator currentAnimation = currentAppearingAnimations.get(child); 1204e64ea87f966e995f5e1a77f991b9da0ed21ffab0Chet Haase if (currentAnimation != null) { 1205e64ea87f966e995f5e1a77f991b9da0ed21ffab0Chet Haase currentAnimation.cancel(); 1206e64ea87f966e995f5e1a77f991b9da0ed21ffab0Chet Haase } 12075d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase if (mDisappearingAnim == null) { 1208c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin if (hasListeners()) { 1209c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin ArrayList<TransitionListener> listeners = 1210c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin (ArrayList<TransitionListener>) mListeners.clone(); 1211c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin for (TransitionListener listener : listeners) { 12125d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase listener.endTransition(LayoutTransition.this, parent, child, DISAPPEARING); 12135d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase } 12145d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase } 12155d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase return; 12165d6d7b9c3d76ba0bf72906d54c2ef366be149a23Chet Haase } 1217a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase Animator anim = mDisappearingAnim.clone(); 121821cd1389d2ef218b20994b617c57af120841a57fChet Haase anim.setStartDelay(mDisappearingDelay); 121921cd1389d2ef218b20994b617c57af120841a57fChet Haase anim.setDuration(mDisappearingDuration); 122033d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase if (mDisappearingInterpolator != sDisappearingInterpolator) { 122133d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase anim.setInterpolator(mDisappearingInterpolator); 122233d08762d8e8d32422903929ad2b72774d9f8c87Chet Haase } 122321cd1389d2ef218b20994b617c57af120841a57fChet Haase anim.setTarget(child); 1224a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase final float preAnimAlpha = child.getAlpha(); 1225a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase anim.addListener(new AnimatorListenerAdapter() { 1226a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase @Override 1227a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase public void onAnimationEnd(Animator anim) { 1228a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase currentDisappearingAnimations.remove(child); 1229a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase child.setAlpha(preAnimAlpha); 1230c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin if (hasListeners()) { 1231c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin ArrayList<TransitionListener> listeners = 1232c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin (ArrayList<TransitionListener>) mListeners.clone(); 1233c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin for (TransitionListener listener : listeners) { 123421cd1389d2ef218b20994b617c57af120841a57fChet Haase listener.endTransition(LayoutTransition.this, parent, child, DISAPPEARING); 123521cd1389d2ef218b20994b617c57af120841a57fChet Haase } 123621cd1389d2ef218b20994b617c57af120841a57fChet Haase } 1237a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase } 1238a553113a1f88e112b0999c12c7c2e8d724ed7fa8Chet Haase }); 1239a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase if (anim instanceof ObjectAnimator) { 1240a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase ((ObjectAnimator) anim).setCurrentPlayTime(0); 124121cd1389d2ef218b20994b617c57af120841a57fChet Haase } 1242e8e45d32fd1f67fed1b70d0fc19d2f91a76f128eChet Haase currentDisappearingAnimations.put(child, anim); 124321cd1389d2ef218b20994b617c57af120841a57fChet Haase anim.start(); 124421cd1389d2ef218b20994b617c57af120841a57fChet Haase } 124521cd1389d2ef218b20994b617c57af120841a57fChet Haase 124621cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 124721cd1389d2ef218b20994b617c57af120841a57fChet Haase * This method is called by ViewGroup when a child view is about to be added to the 124821cd1389d2ef218b20994b617c57af120841a57fChet Haase * container. This callback starts the process of a transition; we grab the starting 124921cd1389d2ef218b20994b617c57af120841a57fChet Haase * values, listen for changes to all of the children of the container, and start appropriate 125021cd1389d2ef218b20994b617c57af120841a57fChet Haase * animations. 125121cd1389d2ef218b20994b617c57af120841a57fChet Haase * 125221cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param parent The ViewGroup to which the View is being added. 125321cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param child The View being added to the ViewGroup. 12540d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * @param changesLayout Whether the removal will cause changes in the layout of other views 12550d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * in the container. INVISIBLE views becoming VISIBLE will not cause changes and thus will not 12560d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * affect CHANGE_APPEARING or CHANGE_DISAPPEARING animations. 125721cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 12580d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase private void addChild(ViewGroup parent, View child, boolean changesLayout) { 1259ab3a776827365b6bb413052a5e093bbc87265728Chet Haase if (parent.getWindowVisibility() != View.VISIBLE) { 1260ab3a776827365b6bb413052a5e093bbc87265728Chet Haase return; 1261ab3a776827365b6bb413052a5e093bbc87265728Chet Haase } 12627dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase if ((mTransitionTypes & FLAG_APPEARING) == FLAG_APPEARING) { 12637dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase // Want disappearing animations to finish up before proceeding 12647dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase cancel(DISAPPEARING); 12657dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 12667dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase if (changesLayout && (mTransitionTypes & FLAG_CHANGE_APPEARING) == FLAG_CHANGE_APPEARING) { 12670d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase // Also, cancel changing animations so that we start fresh ones from current locations 12680d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase cancel(CHANGE_APPEARING); 12697dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase cancel(CHANGING); 12700d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase } 1271c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin if (hasListeners() && (mTransitionTypes & FLAG_APPEARING) == FLAG_APPEARING) { 1272c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin ArrayList<TransitionListener> listeners = 1273c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin (ArrayList<TransitionListener>) mListeners.clone(); 1274c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin for (TransitionListener listener : listeners) { 127521cd1389d2ef218b20994b617c57af120841a57fChet Haase listener.startTransition(this, parent, child, APPEARING); 127621cd1389d2ef218b20994b617c57af120841a57fChet Haase } 127721cd1389d2ef218b20994b617c57af120841a57fChet Haase } 12787dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase if (changesLayout && (mTransitionTypes & FLAG_CHANGE_APPEARING) == FLAG_CHANGE_APPEARING) { 12790d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase runChangeTransition(parent, child, APPEARING); 12800d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase } 12817dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase if ((mTransitionTypes & FLAG_APPEARING) == FLAG_APPEARING) { 12827dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase runAppearingTransition(parent, child); 12837dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 12847dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 12857dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase 1286c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin private boolean hasListeners() { 1287c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin return mListeners != null && mListeners.size() > 0; 1288c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin } 1289c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin 12907dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase /** 12917dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * This method is called by ViewGroup when there is a call to layout() on the container 12927dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * with this LayoutTransition. If the CHANGING transition is enabled and if there is no other 12937dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * transition currently running on the container, then this call runs a CHANGING transition. 12947dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * The transition does not start immediately; it just sets up the mechanism to run if any 12957dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * of the children of the container change their layout parameters (similar to 12967dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * the CHANGE_APPEARING and CHANGE_DISAPPEARING transitions). 12977dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * 12987dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @param parent The ViewGroup whose layout() method has been called. 12997dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * 13007dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase * @hide 13017dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase */ 13027dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase public void layoutChange(ViewGroup parent) { 1303ab3a776827365b6bb413052a5e093bbc87265728Chet Haase if (parent.getWindowVisibility() != View.VISIBLE) { 1304ab3a776827365b6bb413052a5e093bbc87265728Chet Haase return; 1305ab3a776827365b6bb413052a5e093bbc87265728Chet Haase } 13067dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase if ((mTransitionTypes & FLAG_CHANGING) == FLAG_CHANGING && !isRunning()) { 13077dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase // This method is called for all calls to layout() in the container, including 13087dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase // those caused by add/remove/hide/show events, which will already have set up 13097dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase // transition animations. Avoid setting up CHANGING animations in this case; only 13107dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase // do so when there is not a transition already running on the container. 13117dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase runChangeTransition(parent, null, CHANGING); 13127dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 131321cd1389d2ef218b20994b617c57af120841a57fChet Haase } 131421cd1389d2ef218b20994b617c57af120841a57fChet Haase 131521cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 13165e25c2c14593caee5638603120553ae1ec530f85Chet Haase * This method is called by ViewGroup when a child view is about to be added to the 13175e25c2c14593caee5638603120553ae1ec530f85Chet Haase * container. This callback starts the process of a transition; we grab the starting 13185e25c2c14593caee5638603120553ae1ec530f85Chet Haase * values, listen for changes to all of the children of the container, and start appropriate 13195e25c2c14593caee5638603120553ae1ec530f85Chet Haase * animations. 13205e25c2c14593caee5638603120553ae1ec530f85Chet Haase * 13215e25c2c14593caee5638603120553ae1ec530f85Chet Haase * @param parent The ViewGroup to which the View is being added. 13225e25c2c14593caee5638603120553ae1ec530f85Chet Haase * @param child The View being added to the ViewGroup. 13235e25c2c14593caee5638603120553ae1ec530f85Chet Haase */ 13240d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase public void addChild(ViewGroup parent, View child) { 13250d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase addChild(parent, child, true); 13260d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase } 13270d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase 13280d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase /** 13290d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * @deprecated Use {@link #showChild(android.view.ViewGroup, android.view.View, int)}. 13300d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase */ 13310d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase @Deprecated 13325e25c2c14593caee5638603120553ae1ec530f85Chet Haase public void showChild(ViewGroup parent, View child) { 13330d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase addChild(parent, child, true); 13340d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase } 13350d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase 13360d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase /** 13370d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * This method is called by ViewGroup when a child view is about to be made visible in the 13380d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * container. This callback starts the process of a transition; we grab the starting 13390d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * values, listen for changes to all of the children of the container, and start appropriate 13400d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * animations. 13410d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * 13420d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * @param parent The ViewGroup in which the View is being made visible. 13430d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * @param child The View being made visible. 13440d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * @param oldVisibility The previous visibility value of the child View, either 13450d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * {@link View#GONE} or {@link View#INVISIBLE}. 13460d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase */ 13470d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase public void showChild(ViewGroup parent, View child, int oldVisibility) { 13480d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase addChild(parent, child, oldVisibility == View.GONE); 13495e25c2c14593caee5638603120553ae1ec530f85Chet Haase } 13505e25c2c14593caee5638603120553ae1ec530f85Chet Haase 13515e25c2c14593caee5638603120553ae1ec530f85Chet Haase /** 135221cd1389d2ef218b20994b617c57af120841a57fChet Haase * This method is called by ViewGroup when a child view is about to be removed from the 135321cd1389d2ef218b20994b617c57af120841a57fChet Haase * container. This callback starts the process of a transition; we grab the starting 135421cd1389d2ef218b20994b617c57af120841a57fChet Haase * values, listen for changes to all of the children of the container, and start appropriate 135521cd1389d2ef218b20994b617c57af120841a57fChet Haase * animations. 135621cd1389d2ef218b20994b617c57af120841a57fChet Haase * 135721cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param parent The ViewGroup from which the View is being removed. 135821cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param child The View being removed from the ViewGroup. 13590d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * @param changesLayout Whether the removal will cause changes in the layout of other views 13600d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * in the container. Views becoming INVISIBLE will not cause changes and thus will not 13610d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * affect CHANGE_APPEARING or CHANGE_DISAPPEARING animations. 136221cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 13630d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase private void removeChild(ViewGroup parent, View child, boolean changesLayout) { 1364ab3a776827365b6bb413052a5e093bbc87265728Chet Haase if (parent.getWindowVisibility() != View.VISIBLE) { 1365ab3a776827365b6bb413052a5e093bbc87265728Chet Haase return; 1366ab3a776827365b6bb413052a5e093bbc87265728Chet Haase } 13677dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase if ((mTransitionTypes & FLAG_DISAPPEARING) == FLAG_DISAPPEARING) { 13687dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase // Want appearing animations to finish up before proceeding 13697dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase cancel(APPEARING); 13707dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 13717dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase if (changesLayout && 13727dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase (mTransitionTypes & FLAG_CHANGE_DISAPPEARING) == FLAG_CHANGE_DISAPPEARING) { 13730d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase // Also, cancel changing animations so that we start fresh ones from current locations 13740d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase cancel(CHANGE_DISAPPEARING); 13757dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase cancel(CHANGING); 13760d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase } 1377c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin if (hasListeners() && (mTransitionTypes & FLAG_DISAPPEARING) == FLAG_DISAPPEARING) { 1378c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin ArrayList<TransitionListener> listeners = (ArrayList<TransitionListener>) mListeners 1379c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin .clone(); 1380c20fc8daf56eb348fa4a9355a9e33b0ebc468699Luca Zanolin for (TransitionListener listener : listeners) { 138121cd1389d2ef218b20994b617c57af120841a57fChet Haase listener.startTransition(this, parent, child, DISAPPEARING); 138221cd1389d2ef218b20994b617c57af120841a57fChet Haase } 138321cd1389d2ef218b20994b617c57af120841a57fChet Haase } 13847dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase if (changesLayout && 13857dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase (mTransitionTypes & FLAG_CHANGE_DISAPPEARING) == FLAG_CHANGE_DISAPPEARING) { 13860d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase runChangeTransition(parent, child, DISAPPEARING); 13870d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase } 13887dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase if ((mTransitionTypes & FLAG_DISAPPEARING) == FLAG_DISAPPEARING) { 13897dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase runDisappearingTransition(parent, child); 13907dd4a536a125d5e9573e82c39581bf9ee3922424Chet Haase } 139121cd1389d2ef218b20994b617c57af120841a57fChet Haase } 139221cd1389d2ef218b20994b617c57af120841a57fChet Haase 139321cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 13945e25c2c14593caee5638603120553ae1ec530f85Chet Haase * This method is called by ViewGroup when a child view is about to be removed from the 13955e25c2c14593caee5638603120553ae1ec530f85Chet Haase * container. This callback starts the process of a transition; we grab the starting 13965e25c2c14593caee5638603120553ae1ec530f85Chet Haase * values, listen for changes to all of the children of the container, and start appropriate 13975e25c2c14593caee5638603120553ae1ec530f85Chet Haase * animations. 13985e25c2c14593caee5638603120553ae1ec530f85Chet Haase * 13995e25c2c14593caee5638603120553ae1ec530f85Chet Haase * @param parent The ViewGroup from which the View is being removed. 14005e25c2c14593caee5638603120553ae1ec530f85Chet Haase * @param child The View being removed from the ViewGroup. 14015e25c2c14593caee5638603120553ae1ec530f85Chet Haase */ 14020d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase public void removeChild(ViewGroup parent, View child) { 14030d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase removeChild(parent, child, true); 14040d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase } 14050d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase 14060d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase /** 14070d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * @deprecated Use {@link #hideChild(android.view.ViewGroup, android.view.View, int)}. 14080d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase */ 14090d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase @Deprecated 14105e25c2c14593caee5638603120553ae1ec530f85Chet Haase public void hideChild(ViewGroup parent, View child) { 14110d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase removeChild(parent, child, true); 14120d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase } 14130d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase 14140d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase /** 14150d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * This method is called by ViewGroup when a child view is about to be hidden in 14160d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * container. This callback starts the process of a transition; we grab the starting 14170d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * values, listen for changes to all of the children of the container, and start appropriate 14180d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * animations. 14190d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * 14200d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * @param parent The parent ViewGroup of the View being hidden. 14210d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * @param child The View being hidden. 14220d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * @param newVisibility The new visibility value of the child View, either 14230d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase * {@link View#GONE} or {@link View#INVISIBLE}. 14240d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase */ 14250d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase public void hideChild(ViewGroup parent, View child, int newVisibility) { 14260d29936ec3b5545a415e8d032150ea987aab36e3Chet Haase removeChild(parent, child, newVisibility == View.GONE); 14275e25c2c14593caee5638603120553ae1ec530f85Chet Haase } 14285e25c2c14593caee5638603120553ae1ec530f85Chet Haase 14295e25c2c14593caee5638603120553ae1ec530f85Chet Haase /** 143021cd1389d2ef218b20994b617c57af120841a57fChet Haase * Add a listener that will be called when the bounds of the view change due to 143121cd1389d2ef218b20994b617c57af120841a57fChet Haase * layout processing. 143221cd1389d2ef218b20994b617c57af120841a57fChet Haase * 143321cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param listener The listener that will be called when layout bounds change. 143421cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 143521cd1389d2ef218b20994b617c57af120841a57fChet Haase public void addTransitionListener(TransitionListener listener) { 143621cd1389d2ef218b20994b617c57af120841a57fChet Haase if (mListeners == null) { 143721cd1389d2ef218b20994b617c57af120841a57fChet Haase mListeners = new ArrayList<TransitionListener>(); 143821cd1389d2ef218b20994b617c57af120841a57fChet Haase } 143921cd1389d2ef218b20994b617c57af120841a57fChet Haase mListeners.add(listener); 144021cd1389d2ef218b20994b617c57af120841a57fChet Haase } 144121cd1389d2ef218b20994b617c57af120841a57fChet Haase 144221cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 144321cd1389d2ef218b20994b617c57af120841a57fChet Haase * Remove a listener for layout changes. 144421cd1389d2ef218b20994b617c57af120841a57fChet Haase * 144521cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param listener The listener for layout bounds change. 144621cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 144721cd1389d2ef218b20994b617c57af120841a57fChet Haase public void removeTransitionListener(TransitionListener listener) { 144821cd1389d2ef218b20994b617c57af120841a57fChet Haase if (mListeners == null) { 144921cd1389d2ef218b20994b617c57af120841a57fChet Haase return; 145021cd1389d2ef218b20994b617c57af120841a57fChet Haase } 145121cd1389d2ef218b20994b617c57af120841a57fChet Haase mListeners.remove(listener); 145221cd1389d2ef218b20994b617c57af120841a57fChet Haase } 145321cd1389d2ef218b20994b617c57af120841a57fChet Haase 145421cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 145521cd1389d2ef218b20994b617c57af120841a57fChet Haase * Gets the current list of listeners for layout changes. 145621cd1389d2ef218b20994b617c57af120841a57fChet Haase * @return 145721cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 145821cd1389d2ef218b20994b617c57af120841a57fChet Haase public List<TransitionListener> getTransitionListeners() { 145921cd1389d2ef218b20994b617c57af120841a57fChet Haase return mListeners; 146021cd1389d2ef218b20994b617c57af120841a57fChet Haase } 146121cd1389d2ef218b20994b617c57af120841a57fChet Haase 146221cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 146321cd1389d2ef218b20994b617c57af120841a57fChet Haase * This interface is used for listening to starting and ending events for transitions. 146421cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 146521cd1389d2ef218b20994b617c57af120841a57fChet Haase public interface TransitionListener { 146621cd1389d2ef218b20994b617c57af120841a57fChet Haase 146721cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 14689c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * This event is sent to listeners when any type of transition animation begins. 146921cd1389d2ef218b20994b617c57af120841a57fChet Haase * 147021cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param transition The LayoutTransition sending out the event. 147121cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param container The ViewGroup on which the transition is playing. 14729c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * @param view The View object being affected by the transition animation. 14739c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * @param transitionType The type of transition that is beginning, 14749c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * {@link android.animation.LayoutTransition#APPEARING}, 14759c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * {@link android.animation.LayoutTransition#DISAPPEARING}, 14769c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * {@link android.animation.LayoutTransition#CHANGE_APPEARING}, or 14779c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * {@link android.animation.LayoutTransition#CHANGE_DISAPPEARING}. 147821cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 147921cd1389d2ef218b20994b617c57af120841a57fChet Haase public void startTransition(LayoutTransition transition, ViewGroup container, 148021cd1389d2ef218b20994b617c57af120841a57fChet Haase View view, int transitionType); 148121cd1389d2ef218b20994b617c57af120841a57fChet Haase 148221cd1389d2ef218b20994b617c57af120841a57fChet Haase /** 14839c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * This event is sent to listeners when any type of transition animation ends. 148421cd1389d2ef218b20994b617c57af120841a57fChet Haase * 148521cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param transition The LayoutTransition sending out the event. 148621cd1389d2ef218b20994b617c57af120841a57fChet Haase * @param container The ViewGroup on which the transition is playing. 14879c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * @param view The View object being affected by the transition animation. 14889c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * @param transitionType The type of transition that is ending, 14899c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * {@link android.animation.LayoutTransition#APPEARING}, 14909c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * {@link android.animation.LayoutTransition#DISAPPEARING}, 14919c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * {@link android.animation.LayoutTransition#CHANGE_APPEARING}, or 14929c0874408cfc6f6f4e4561973ca5ae52a5982db7Chet Haase * {@link android.animation.LayoutTransition#CHANGE_DISAPPEARING}. 149321cd1389d2ef218b20994b617c57af120841a57fChet Haase */ 149421cd1389d2ef218b20994b617c57af120841a57fChet Haase public void endTransition(LayoutTransition transition, ViewGroup container, 149521cd1389d2ef218b20994b617c57af120841a57fChet Haase View view, int transitionType); 149621cd1389d2ef218b20994b617c57af120841a57fChet Haase } 149721cd1389d2ef218b20994b617c57af120841a57fChet Haase 1498abb7d66049c176459779a22810b3931d263f68e6Chet Haase} 1499