Transition.java revision 31a217290cf376d0573fc36e21c8940987485019
1faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/*
2faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Copyright (C) 2013 The Android Open Source Project
3faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase *
4faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Licensed under the Apache License, Version 2.0 (the "License");
5faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * you may not use this file except in compliance with the License.
6faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * You may obtain a copy of the License at
7faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase *
8faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase *      http://www.apache.org/licenses/LICENSE-2.0
9faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase *
10faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Unless required by applicable law or agreed to in writing, software
11faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * distributed under the License is distributed on an "AS IS" BASIS,
12faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * See the License for the specific language governing permissions and
14faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * limitations under the License.
15faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */
166ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
17d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haasepackage android.transition;
18faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
19faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.animation.Animator;
20faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.animation.AnimatorListenerAdapter;
21faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.animation.TimeInterpolator;
22d6107a3170df61d9e776fcd5666acfc9135c6f16George Mountimport android.graphics.Rect;
2308735185f8105710e18ad02297461bec9268e514Chet Haaseimport android.util.ArrayMap;
24c43524f3869cc0d36974fce61986017093f2ecd2Chet Haaseimport android.util.Log;
25faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.util.LongSparseArray;
26faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.util.SparseArray;
27d6107a3170df61d9e776fcd5666acfc9135c6f16George Mountimport android.util.SparseLongArray;
28faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.SurfaceView;
29faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.TextureView;
30faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.View;
31faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.ViewGroup;
32faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.ViewOverlay;
33cf68aad3164303df59b2a669d186a94533c9c743George Mountimport android.view.WindowId;
34faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.widget.ListView;
35ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haaseimport android.widget.Spinner;
36faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
37faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport java.util.ArrayList;
38d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haaseimport java.util.List;
39faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
40faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/**
41faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * A Transition holds information about animations that will be run on its
42faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * targets during a scene change. Subclasses of this abstract class may
43d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * choreograph several child transitions ({@link TransitionSet} or they may
44faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * perform custom animations themselves. Any Transition has two main jobs:
45faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * (1) capture property values, and (2) play animations based on changes to
46faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * captured property values. A custom transition knows what property values
47faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * on View objects are of interest to it, and also knows how to animate
48faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * changes to those values. For example, the {@link Fade} transition tracks
49faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * changes to visibility-related properties and is able to construct and run
50faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * animations that fade items in or out based on changes to those properties.
51faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase *
52faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * <p>Note: Transitions may not work correctly with either {@link SurfaceView}
53faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * or {@link TextureView}, due to the way that these views are displayed
54faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * on the screen. For SurfaceView, the problem is that the view is updated from
55faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * a non-UI thread, so changes to the view due to transitions (such as moving
56faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * and resizing the view) may be out of sync with the display inside those bounds.
57faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * TextureView is more compatible with transitions in general, but some
58d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * specific transitions (such as {@link Fade}) may not be compatible
59faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * with TextureView because they rely on {@link ViewOverlay} functionality,
60faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * which does not currently work with TextureView.</p>
61d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
62d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * <p>Transitions can be declared in XML resource files inside the <code>res/transition</code>
63d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * directory. Transition resources consist of a tag name for one of the Transition
64d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * subclasses along with attributes to define some of the attributes of that transition.
65d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * For example, here is a minimal resource file that declares a {@link ChangeBounds} transition:
66d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
67d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@sample development/samples/ApiDemos/res/transition/changebounds.xml ChangeBounds}
68d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
69d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * <p>{@link android.transition.Explode} transition:</p>
70d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount *
71d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@sample development/samples/ApiDemos/res/transition/explode.xml Explode}
72d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount *
73d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * <p>{@link android.transition.MoveImage} transition:</p>
74d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount *
75d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@sample development/samples/ApiDemos/res/transition/move_image.xml MoveImage}
76d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount *
77d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * <p>Note that attributes for the transition are not required, just as they are
78d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * optional when declared in code; Transitions created from XML resources will use
79d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * the same defaults as their code-created equivalents. Here is a slightly more
80d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * elaborate example which declares a {@link TransitionSet} transition with
81d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link ChangeBounds} and {@link Fade} child transitions:</p>
82d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
83d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@sample
84d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * development/samples/ApiDemos/res/transition/changebounds_fadeout_sequential.xml TransitionSet}
85d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
86d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * <p>In this example, the transitionOrdering attribute is used on the TransitionSet
87d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * object to change from the default {@link TransitionSet#ORDERING_TOGETHER} behavior
88d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * to be {@link TransitionSet#ORDERING_SEQUENTIAL} instead. Also, the {@link Fade}
89d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * transition uses a fadingMode of {@link Fade#OUT} instead of the default
90d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * out-in behavior. Finally, note the use of the <code>targets</code> sub-tag, which
91d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * takes a set of {@link android.R.styleable#TransitionTarget target} tags, each
92d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * of which lists a specific <code>targetId</code> which this transition acts upon.
93d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * Use of targets is optional, but can be used to either limit the time spent checking
94d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * attributes on unchanging views, or limiting the types of animations run on specific views.
95d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * In this case, we know that only the <code>grayscaleContainer</code> will be
96d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * disappearing, so we choose to limit the {@link Fade} transition to only that view.</p>
97d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
98d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * Further information on XML resource descriptions for transitions can be found for
99d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link android.R.styleable#Transition}, {@link android.R.styleable#TransitionSet},
100d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link android.R.styleable#TransitionTarget}, {@link android.R.styleable#Fade}, and
101d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link android.R.styleable#Slide}.
102d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
103faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */
1046ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haasepublic abstract class Transition implements Cloneable {
105faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
106faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    private static final String LOG_TAG = "Transition";
107faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    static final boolean DBG = false;
108faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
109199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    private String mName = getClass().getName();
110199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
111faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    long mStartDelay = -1;
112faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    long mDuration = -1;
113faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    TimeInterpolator mInterpolator = null;
114d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    ArrayList<Integer> mTargetIds = new ArrayList<Integer>();
115d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    ArrayList<View> mTargets = new ArrayList<View>();
116ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Integer> mTargetIdExcludes = null;
117ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<View> mTargetExcludes = null;
118ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Class> mTargetTypeExcludes = null;
119ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Integer> mTargetIdChildExcludes = null;
120ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<View> mTargetChildExcludes = null;
121ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Class> mTargetTypeChildExcludes = null;
1226ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    private TransitionValuesMaps mStartValues = new TransitionValuesMaps();
1236ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    private TransitionValuesMaps mEndValues = new TransitionValuesMaps();
124d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    TransitionSet mParent = null;
1256ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
126199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    // Per-animator information used for later canceling when future transitions overlap
127199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    private static ThreadLocal<ArrayMap<Animator, AnimationInfo>> sRunningAnimators =
128199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            new ThreadLocal<ArrayMap<Animator, AnimationInfo>>();
129199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
130d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    // Scene Root is set at createAnimator() time in the cloned Transition
1316ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    ViewGroup mSceneRoot = null;
1326ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
133b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // Whether removing views from their parent is possible. This is only for views
134b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // in the start scene, which are no longer in the view hierarchy. This property
135b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // is determined by whether the previous Scene was created from a layout
136b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // resource, and thus the views from the exited scene are going away anyway
137b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // and can be removed as necessary to achieve a particular effect, such as
138b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // removing them from parents to add them to overlays.
139b7a7fc9d233bad507ce893882352618b13647058Chet Haase    boolean mCanRemoveViews = false;
140b7a7fc9d233bad507ce893882352618b13647058Chet Haase
141e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    // Track all animators in use in case the transition gets canceled and needs to
142e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    // cancel running animators
143e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    private ArrayList<Animator> mCurrentAnimators = new ArrayList<Animator>();
144e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase
145faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    // Number of per-target instances of this Transition currently running. This count is
146199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    // determined by calls to start() and end()
147faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    int mNumInstances = 0;
148faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
149199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    // Whether this transition is currently paused, due to a call to pause()
150199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    boolean mPaused = false;
151c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase
152a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase    // Whether this transition has ended. Used to avoid pause/resume on transitions
153a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase    // that have completed
154a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase    private boolean mEnded = false;
155a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase
156c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase    // The set of listeners to be sent transition lifecycle events.
157faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    ArrayList<TransitionListener> mListeners = null;
158faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
159d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    // The set of animators collected from calls to createAnimator(),
160d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    // to be run in runAnimators()
161199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    ArrayList<Animator> mAnimators = new ArrayList<Animator>();
162c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase
163d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    // The function for calculating the Animation start delay.
164d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    TransitionPropagation mPropagation;
165d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
166d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    // The rectangular region for Transitions like Explode and TransitionPropagations
167d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    // like CircularPropagation
168d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    EpicenterCallback mEpicenterCallback;
169d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
170faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
171faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Constructs a Transition object with no target objects. A transition with
172faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * no targets defaults to running on all target objects in the scene hierarchy
173d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * (if the transition is not contained in a TransitionSet), or all target
174d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * objects passed down from its parent (if it is in a TransitionSet).
175faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
176faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public Transition() {}
177faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
178faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
179faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the duration of this transition. By default, there is no duration
180faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * (indicated by a negative number), which means that the Animator created by
181faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the transition will have its own specified duration. If the duration of a
182faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Transition is set, that duration will override the Animator duration.
183faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
184faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param duration The length of the animation, in milliseconds.
185faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @return This transition object.
186d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @attr ref android.R.styleable#Transition_duration
187faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
188faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public Transition setDuration(long duration) {
189faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mDuration = duration;
190faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return this;
191faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
192faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
193199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
194199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the duration set on this transition. If no duration has been set,
195199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the returned value will be negative, indicating that resulting animators will
196199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * retain their own durations.
197199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
198d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The duration set on this transition, in milliseconds, if one has been
199d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * set, otherwise returns a negative number.
200199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
201faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public long getDuration() {
202faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mDuration;
203faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
204faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
205faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
206faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the startDelay of this transition. By default, there is no delay
207faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * (indicated by a negative number), which means that the Animator created by
208faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the transition will have its own specified startDelay. If the delay of a
209faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Transition is set, that delay will override the Animator delay.
210faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
211faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param startDelay The length of the delay, in milliseconds.
212d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
213d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @attr ref android.R.styleable#Transition_startDelay
214faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
215d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition setStartDelay(long startDelay) {
216faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mStartDelay = startDelay;
217d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
218faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
219faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
220199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
221199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the startDelay set on this transition. If no startDelay has been set,
222199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the returned value will be negative, indicating that resulting animators will
223199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * retain their own startDelays.
224199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
225d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The startDelay set on this transition, in milliseconds, if one has
226d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * been set, otherwise returns a negative number.
227199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
228faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public long getStartDelay() {
229faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mStartDelay;
230faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
231faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
232faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
233faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the interpolator of this transition. By default, the interpolator
234faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * is null, which means that the Animator created by the transition
235faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * will have its own specified interpolator. If the interpolator of a
236faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Transition is set, that interpolator will override the Animator interpolator.
237faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
238faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param interpolator The time interpolator used by the transition
239d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
240d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @attr ref android.R.styleable#Transition_interpolator
241faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
242d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition setInterpolator(TimeInterpolator interpolator) {
243faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mInterpolator = interpolator;
244d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
245faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
246faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
247199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
248199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the interpolator set on this transition. If no interpolator has been set,
249199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the returned value will be null, indicating that resulting animators will
250199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * retain their own interpolators.
251199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
252199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return The interpolator set on this transition, if one has been set, otherwise
253199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * returns null.
254199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
255faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public TimeInterpolator getInterpolator() {
256faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mInterpolator;
257faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
258faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
259faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
260199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the set of property names used stored in the {@link TransitionValues}
261d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * object passed into {@link #captureStartValues(TransitionValues)} that
262199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * this transition cares about for the purposes of canceling overlapping animations.
263199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * When any transition is started on a given scene root, all transitions
264199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * currently running on that same scene root are checked to see whether the
265199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * properties on which they based their animations agree with the end values of
266199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the same properties in the new transition. If the end values are not equal,
267199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * then the old animation is canceled since the new transition will start a new
268199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animation to these new values. If the values are equal, the old animation is
269199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * allowed to continue and no new animation is started for that transition.
270199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
271199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * <p>A transition does not need to override this method. However, not doing so
272199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * will mean that the cancellation logic outlined in the previous paragraph
273199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * will be skipped for that transition, possibly leading to artifacts as
274199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * old transitions and new transitions on the same targets run in parallel,
275199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animating views toward potentially different end values.</p>
276199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
277199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return An array of property names as described in the class documentation for
278199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * {@link TransitionValues}. The default implementation returns <code>null</code>.
279199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
280199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public String[] getTransitionProperties() {
281199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return null;
282199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
283199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
284199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
285d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * This method creates an animation that will be run for this transition
286d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * given the information in the startValues and endValues structures captured
287d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * earlier for the start and end scenes. Subclasses of Transition should override
288d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * this method. The method should only be called by the transition system; it is
289d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * not intended to be called from external classes.
290d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
291d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>This method is called by the transition's parent (all the way up to the
292faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * topmost Transition in the hierarchy) with the sceneRoot and start/end
2932ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * values that the transition may need to set up initial target values
2942ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * and construct an appropriate animation. For example, if an overall
295d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Transition is a {@link TransitionSet} consisting of several
296faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * child transitions in sequence, then some of the child transitions may
297faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * want to set initial values on target views prior to the overall
2982ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * Transition commencing, to put them in an appropriate state for the
299faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * delay between that start and the child Transition start time. For
300faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * example, a transition that fades an item in may wish to set the starting
301faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * alpha value to 0, to avoid it blinking in prior to the transition
302faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * actually starting the animation. This is necessary because the scene
303faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * change that triggers the Transition will automatically set the end-scene
304faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * on all target views, so a Transition that wants to animate from a
305d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * different value should set that value prior to returning from this method.</p>
306faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
307faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * <p>Additionally, a Transition can perform logic to determine whether
308faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the transition needs to run on the given target and start/end values.
309faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * For example, a transition that resizes objects on the screen may wish
310faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * to avoid running for views which are not present in either the start
311d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * or end scenes.</p>
3122ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     *
3132ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * <p>If there is an animator created and returned from this method, the
3142ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * transition mechanism will apply any applicable duration, startDelay,
3152ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * and interpolator to that animation and start it. A return value of
3162ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * <code>null</code> indicates that no animation should run. The default
3172ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * implementation returns null.</p>
318faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
319faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * <p>The method is called for every applicable target object, which is
320faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * stored in the {@link TransitionValues#view} field.</p>
321faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
322d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
323d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param sceneRoot The root of the transition hierarchy.
324d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param startValues The values for a specific target in the start scene.
325d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param endValues The values for the target in the end scene.
326d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return A Animator to be started at the appropriate time in the
327d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * overall transition for this scene change. A null value means no animation
328d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * should be run.
329faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
330d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
331faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues endValues) {
3322ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase        return null;
333faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
334faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
335faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
336d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * This method, essentially a wrapper around all calls to createAnimator for all
337d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * possible target views, is called with the entire set of start/end
338faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * values. The implementation in Transition iterates through these lists
339d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * and calls {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}
340faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * with each set of start/end values on this transition. The
341d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * TransitionSet subclass overrides this method and delegates it to
3422ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * each of its children in succession.
343faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
344faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
345faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
346d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
3476ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValuesMaps endValues) {
348c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (DBG) {
349d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            Log.d(LOG_TAG, "createAnimators() for " + this);
350c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
3516ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        ArrayMap<View, TransitionValues> endCopy =
3526ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                new ArrayMap<View, TransitionValues>(endValues.viewValues);
353faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        SparseArray<TransitionValues> endIdCopy =
3546ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                new SparseArray<TransitionValues>(endValues.idValues.size());
3556ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        for (int i = 0; i < endValues.idValues.size(); ++i) {
3566ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            int id = endValues.idValues.keyAt(i);
3576ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            endIdCopy.put(id, endValues.idValues.valueAt(i));
358faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
359faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        LongSparseArray<TransitionValues> endItemIdCopy =
3606ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                new LongSparseArray<TransitionValues>(endValues.itemIdValues.size());
3616ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        for (int i = 0; i < endValues.itemIdValues.size(); ++i) {
3626ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            long id = endValues.itemIdValues.keyAt(i);
3636ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            endItemIdCopy.put(id, endValues.itemIdValues.valueAt(i));
364faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
365faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        // Walk through the start values, playing everything we find
366faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        // Remove from the end set as we go
367faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        ArrayList<TransitionValues> startValuesList = new ArrayList<TransitionValues>();
368faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        ArrayList<TransitionValues> endValuesList = new ArrayList<TransitionValues>();
3696ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        for (View view : startValues.viewValues.keySet()) {
370faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues start = null;
371faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues end = null;
372faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            boolean isInListView = false;
373faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (view.getParent() instanceof ListView) {
374faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                isInListView = true;
375faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
376faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (!isInListView) {
377faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                int id = view.getId();
3786ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                start = startValues.viewValues.get(view) != null ?
3796ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        startValues.viewValues.get(view) : startValues.idValues.get(id);
3806ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                if (endValues.viewValues.get(view) != null) {
3816ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    end = endValues.viewValues.get(view);
382faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    endCopy.remove(view);
383c46181a963be736186ae29101625a05b5c1f0ba8Chet Haase                } else if (id != View.NO_ID) {
3846ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    end = endValues.idValues.get(id);
385faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    View removeView = null;
386faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    for (View viewToRemove : endCopy.keySet()) {
387faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        if (viewToRemove.getId() == id) {
388faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                            removeView = viewToRemove;
389faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        }
390faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
391faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    if (removeView != null) {
392faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        endCopy.remove(removeView);
393faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
394faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
395faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endIdCopy.remove(id);
396faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                if (isValidTarget(view, id)) {
397faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    startValuesList.add(start);
398faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    endValuesList.add(end);
399faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
400faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
401faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                ListView parent = (ListView) view.getParent();
402faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                if (parent.getAdapter().hasStableIds()) {
403faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    int position = parent.getPositionForView(view);
404faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    long itemId = parent.getItemIdAtPosition(position);
4056ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    start = startValues.itemIdValues.get(itemId);
406faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    endItemIdCopy.remove(itemId);
407faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    // TODO: deal with targetIDs for itemIDs for ListView items
408faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    startValuesList.add(start);
409faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    endValuesList.add(end);
410faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
411faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
412faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
4136ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        int startItemIdCopySize = startValues.itemIdValues.size();
414faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        for (int i = 0; i < startItemIdCopySize; ++i) {
4156ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            long id = startValues.itemIdValues.keyAt(i);
416faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (isValidTarget(null, id)) {
4176ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues start = startValues.itemIdValues.get(id);
4186ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues end = endValues.itemIdValues.get(id);
419faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endItemIdCopy.remove(id);
420faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                startValuesList.add(start);
421faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endValuesList.add(end);
422faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
423faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
424faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        // Now walk through the remains of the end set
425faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        for (View view : endCopy.keySet()) {
426faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            int id = view.getId();
427faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (isValidTarget(view, id)) {
4286ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues start = startValues.viewValues.get(view) != null ?
4296ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        startValues.viewValues.get(view) : startValues.idValues.get(id);
430faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                TransitionValues end = endCopy.get(view);
431faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endIdCopy.remove(id);
432faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                startValuesList.add(start);
433faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endValuesList.add(end);
434faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
435faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
436faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        int endIdCopySize = endIdCopy.size();
437faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        for (int i = 0; i < endIdCopySize; ++i) {
438faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            int id = endIdCopy.keyAt(i);
439faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (isValidTarget(null, id)) {
4406ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues start = startValues.idValues.get(id);
441faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                TransitionValues end = endIdCopy.get(id);
442faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                startValuesList.add(start);
443faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endValuesList.add(end);
444faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
445faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
446faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        int endItemIdCopySize = endItemIdCopy.size();
447faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        for (int i = 0; i < endItemIdCopySize; ++i) {
448faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            long id = endItemIdCopy.keyAt(i);
449faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            // TODO: Deal with targetIDs and itemIDs
4506ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValues start = startValues.itemIdValues.get(id);
451faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues end = endItemIdCopy.get(id);
452faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            startValuesList.add(start);
453faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            endValuesList.add(end);
454faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
455199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
456d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        long minStartDelay = Long.MAX_VALUE;
457d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        int minAnimator = mAnimators.size();
458d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        SparseLongArray startDelays = new SparseLongArray();
459faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        for (int i = 0; i < startValuesList.size(); ++i) {
460faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues start = startValuesList.get(i);
461faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues end = endValuesList.get(i);
462c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            // Only bother trying to animate with values that differ between start/end
463c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            if (start != null || end != null) {
464c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                if (start == null || !start.equals(end)) {
465c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (DBG) {
466c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        View view = (end != null) ? end.view : start.view;
467c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        Log.d(LOG_TAG, "  differing start/end values for view " +
468c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                view);
469c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        if (start == null || end == null) {
470ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                            Log.d(LOG_TAG, "    " + ((start == null) ?
471ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                                    "start null, end non-null" : "start non-null, end null"));
472c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        } else {
473c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                            for (String key : start.values.keySet()) {
474c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                Object startValue = start.values.get(key);
475c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                Object endValue = end.values.get(key);
476c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                if (startValue != endValue && !startValue.equals(endValue)) {
477c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                    Log.d(LOG_TAG, "    " + key + ": start(" + startValue +
478c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                            "), end(" + endValue +")");
479c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                }
480c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                            }
481c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        }
482c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
483c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    // TODO: what to do about targetIds and itemIds?
484d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    Animator animator = createAnimator(sceneRoot, start, end);
485c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (animator != null) {
486199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        // Save animation info for future cancellation purposes
487199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        View view = null;
488199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        TransitionValues infoValues = null;
489199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        if (end != null) {
490199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            view = end.view;
491199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            String[] properties = getTransitionProperties();
492199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            if (view != null && properties != null && properties.length > 0) {
493199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                infoValues = new TransitionValues();
494199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                infoValues.view = view;
495199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                TransitionValues newValues = endValues.viewValues.get(view);
496199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                if (newValues != null) {
497199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    for (int j = 0; j < properties.length; ++j) {
498199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                        infoValues.values.put(properties[j],
499199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                                newValues.values.get(properties[j]));
500199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    }
501199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                }
502199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                int numExistingAnims = runningAnimators.size();
503199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                for (int j = 0; j < numExistingAnims; ++j) {
504199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    Animator anim = runningAnimators.keyAt(j);
505199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    AnimationInfo info = runningAnimators.get(anim);
506199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    if (info.values != null && info.view == view &&
507199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                            ((info.name == null && getName() == null) ||
508199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                            info.name.equals(getName()))) {
509199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                        if (info.values.equals(infoValues)) {
510199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                            // Favor the old animator
511199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                            animator = null;
512199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                            break;
513199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                        }
514199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    }
515199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                }
516199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
517199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        } else {
518199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            view = (start != null) ? start.view : null;
519199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
520199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        if (animator != null) {
521d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                            if (mPropagation != null) {
522d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                                long delay = mPropagation
523d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                                        .getStartDelay(sceneRoot, this, start, end);
524d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                                startDelays.put(mAnimators.size(), delay);
525d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                                minStartDelay = Math.min(delay, minStartDelay);
526d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                            }
527cf68aad3164303df59b2a669d186a94533c9c743George Mount                            AnimationInfo info = new AnimationInfo(view, getName(),
528cf68aad3164303df59b2a669d186a94533c9c743George Mount                                    sceneRoot.getWindowId(), infoValues);
529199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            runningAnimators.put(animator, info);
530199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            mAnimators.add(animator);
531199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
532c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
533c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                }
534faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
535faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
536d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (minStartDelay != 0) {
537d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            for (int i = 0; i < startDelays.size(); i++) {
538d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                int index = startDelays.keyAt(i);
539d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                Animator animator = mAnimators.get(index);
540d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                long delay = startDelays.valueAt(i) - minStartDelay + animator.getStartDelay();
541d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                animator.setStartDelay(delay);
542d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
543d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
544faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
545faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
546faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
547faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Internal utility method for checking whether a given view/id
548faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * is valid for this transition, where "valid" means that either
549faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition has no target/targetId list (the default, in which
550faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * cause the transition should act on all views in the hiearchy), or
551faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the given view is in the target list or the view id is in the
552faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * targetId list. If the target parameter is null, then the target list
553faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * is not checked (this is in the case of ListView items, where the
554faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * views are ignored and only the ids are used).
555faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
556faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    boolean isValidTarget(View target, long targetId) {
557ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetIdExcludes != null && mTargetIdExcludes.contains(targetId)) {
558ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return false;
559ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
560ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetExcludes != null && mTargetExcludes.contains(target)) {
561ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return false;
562ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
563ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetTypeExcludes != null && target != null) {
564ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            int numTypes = mTargetTypeExcludes.size();
565ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            for (int i = 0; i < numTypes; ++i) {
566ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                Class type = mTargetTypeExcludes.get(i);
567ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (type.isInstance(target)) {
568ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    return false;
569ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
570ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
571ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
572d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (mTargetIds.size() == 0 && mTargets.size() == 0) {
573faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            return true;
574faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
575d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (mTargetIds.size() > 0) {
576d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            for (int i = 0; i < mTargetIds.size(); ++i) {
577d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                if (mTargetIds.get(i) == targetId) {
578faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    return true;
579faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
580faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
581faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
582d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (target != null && mTargets.size() > 0) {
583d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            for (int i = 0; i < mTargets.size(); ++i) {
584d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                if (mTargets.get(i) == target) {
585faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    return true;
586faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
587faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
588faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
589faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return false;
590faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
591faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
592e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount    private static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
593199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = sRunningAnimators.get();
594199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (runningAnimators == null) {
595199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            runningAnimators = new ArrayMap<Animator, AnimationInfo>();
596199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            sRunningAnimators.set(runningAnimators);
597199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
598199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return runningAnimators;
599199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
600199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
601faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
6022ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * This is called internally once all animations have been set up by the
603d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * transition hierarchy.
604faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
605faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
606faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
607d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    protected void runAnimators() {
608199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (DBG) {
609d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            Log.d(LOG_TAG, "runAnimators() on " + this);
610199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
611199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        start();
612199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
613d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        // Now start every Animator that was previously created for this transition
614199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        for (Animator anim : mAnimators) {
615c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            if (DBG) {
616c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                Log.d(LOG_TAG, "  anim: " + anim);
617c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            }
618199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            if (runningAnimators.containsKey(anim)) {
619199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                start();
620199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                runAnimator(anim, runningAnimators);
621199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
622faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
623199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        mAnimators.clear();
624199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        end();
625faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
626faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
627199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    private void runAnimator(Animator animator,
628199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            final ArrayMap<Animator, AnimationInfo> runningAnimators) {
629e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        if (animator != null) {
630e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            // TODO: could be a single listener instance for all of them since it uses the param
631e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animator.addListener(new AnimatorListenerAdapter() {
632e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                @Override
633e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                public void onAnimationStart(Animator animation) {
634e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                    mCurrentAnimators.add(animation);
635e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                }
636e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                @Override
637e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                public void onAnimationEnd(Animator animation) {
638199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    runningAnimators.remove(animation);
639e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                    mCurrentAnimators.remove(animation);
640e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                }
641e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            });
642e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animate(animator);
643e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        }
644e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    }
645e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase
646faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
647d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Captures the values in the start scene for the properties that this
648d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition monitors. These values are then passed as the startValues
649d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * structure in a later call to
650d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
651d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The main concern for an implementation is what the
652d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * properties are that the transition cares about and what the values are
653d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * for all of those properties. The start and end values will be compared
654d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * later during the
655d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}
656d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * method to determine what, if any, animations, should be run.
657d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
658d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Subclasses must implement this method. The method should only be called by the
659d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition system; it is not intended to be called from external classes.</p>
660d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
661d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param transitionValues The holder for any values that the Transition
662d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * wishes to store. Values are stored in the <code>values</code> field
663d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * of this TransitionValues object and are keyed from
664d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * a String value. For example, to store a view's rotation value,
665d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * a transition might call
666d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionValues.values.put("appname:transitionname:rotation",
667d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * view.getRotation())</code>. The target view will already be stored in
668d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * the transitionValues structure when this method is called.
669d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
670d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #captureEndValues(TransitionValues)
671d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
672d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
673d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public abstract void captureStartValues(TransitionValues transitionValues);
674d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
675d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
676d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Captures the values in the end scene for the properties that this
677d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition monitors. These values are then passed as the endValues
678d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * structure in a later call to
679d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
680d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The main concern for an implementation is what the
681faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * properties are that the transition cares about and what the values are
682faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * for all of those properties. The start and end values will be compared
6832ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * later during the
684d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}
6852ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * method to determine what, if any, animations, should be run.
686faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
687d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Subclasses must implement this method. The method should only be called by the
688d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition system; it is not intended to be called from external classes.</p>
689d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
6902ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * @param transitionValues The holder for any values that the Transition
6912ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * wishes to store. Values are stored in the <code>values</code> field
6922ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * of this TransitionValues object and are keyed from
6932ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * a String value. For example, to store a view's rotation value,
6942ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * a transition might call
6952ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * <code>transitionValues.values.put("appname:transitionname:rotation",
6962ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * view.getRotation())</code>. The target view will already be stored in
6972ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * the transitionValues structure when this method is called.
698d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
699d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #captureStartValues(TransitionValues)
700d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
701faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
702d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public abstract void captureEndValues(TransitionValues transitionValues);
703faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
704faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
705d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Adds the id of a target view that this Transition is interested in
706faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * animating. By default, there are no targetIds, and a Transition will
707faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listen for changes on every view in the hierarchy below the sceneRoot
708d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * of the Scene being transitioned into. Setting targetIds constrains
709faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition to only listen for, and act on, views with these IDs.
710faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Views with different IDs, or no IDs whatsoever, will be ignored.
711faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
712d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Note that using ids to specify targets implies that ids should be unique
713d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * within the view hierarchy underneat the scene root.</p>
714d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
715faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @see View#getId()
716d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param targetId The id of a target view, must be a positive number.
717d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition to which the targetId is added.
718d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Returning the same object makes it easier to chain calls during
719d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * construction, such as
720ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <code>transitionSet.addTransitions(new Fade()).addTarget(someId);</code>
721d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
722ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition addTarget(int targetId) {
723d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (targetId > 0) {
724d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargetIds.add(targetId);
725d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
726d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
727d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
728d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
729d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
730d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Removes the given targetId from the list of ids that this Transition
731d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * is interested in animating.
732d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
733d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param targetId The id of a target view, must be a positive number.
734d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition from which the targetId is removed.
735faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returning the same object makes it easier to chain calls during
736faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * construction, such as
737d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).removeTargetId(someId);</code>
738faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
739ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition removeTarget(int targetId) {
740d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (targetId > 0) {
741d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargetIds.remove(targetId);
742d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
743faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return this;
744faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
745faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
746faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
747ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given id to the list of target ids to exclude from this
748ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
749ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should be added to or removed from the excluded list.
750ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
751ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
752ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
753ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
754ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
755ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
756ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
757ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
758ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
759ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
760ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
761ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
762ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param targetId The id of a target to ignore when running this transition.
763ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
764ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
765ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
766ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
767ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(int targetId, boolean exclude) {
768ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetIdExcludes = excludeId(mTargetIdExcludes, targetId, exclude);
769ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
770ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
771ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
772ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
773ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the children of the given id to the list of targets to exclude
774ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * from this transition. The <code>exclude</code> parameter specifies whether
775ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the children of the target should be added to or removed from the excluded list.
776ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Excluding children in this way provides a simple mechanism for excluding all
777ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * children of specific targets, rather than individually excluding each
778ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * child individually.
779ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
780ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
781ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
782ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
783ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
784ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
785ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
786ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
787ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
788ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
789ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
790ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
791ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param targetId The id of a target whose children should be ignored when running
792ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * this transition.
793ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
794ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded-child targets.
795ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
796ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
797ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(int targetId, boolean exclude) {
798ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetIdChildExcludes = excludeId(mTargetIdChildExcludes, targetId, exclude);
799ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
800ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
801ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
802ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
803ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility method to manage the boilerplate code that is the same whether we
804ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * are excluding targets or their children.
805ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
806ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    private ArrayList<Integer> excludeId(ArrayList<Integer> list, int targetId, boolean exclude) {
807ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (targetId > 0) {
808ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (exclude) {
809ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.add(list, targetId);
810ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            } else {
811ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.remove(list, targetId);
812ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
813ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
814ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return list;
815ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
816ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
817ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
818ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given target to the list of targets to exclude from this
819ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
820ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should be added to or removed from the excluded list.
821ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
822ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
823ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
824ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
825ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
826ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
827ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
828ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
829ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
830ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
831ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
832ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
833ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param target The target to ignore when running this transition.
834ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
835ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
836ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
837ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
838ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(View target, boolean exclude) {
839ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetExcludes = excludeView(mTargetExcludes, target, exclude);
840ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
841ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
842ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
843ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
844ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the children of given target to the list of target children
845ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * to exclude from this transition. The <code>exclude</code> parameter specifies
846ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * whether the target should be added to or removed from the excluded list.
847ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
848ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
849ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
850ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
851ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
852ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
853ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
854ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
855ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
856ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
857ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
858ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
859ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param target The target to ignore when running this transition.
860ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
861ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
862ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
863ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
864ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(View target, boolean exclude) {
865ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetChildExcludes = excludeView(mTargetChildExcludes, target, exclude);
866ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
867ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
868ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
869ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
870ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility method to manage the boilerplate code that is the same whether we
871ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * are excluding targets or their children.
872ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
873ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    private ArrayList<View> excludeView(ArrayList<View> list, View target, boolean exclude) {
874ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (target != null) {
875ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (exclude) {
876ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.add(list, target);
877ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            } else {
878ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.remove(list, target);
879ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
880ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
881ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return list;
882ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
883ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
884ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
885ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given type to the list of types to exclude from this
886ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
887ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * type should be added to or removed from the excluded list.
888ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
889ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
890ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
891ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
892ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
893ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
894ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
895ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
896ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
897ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
898ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
899ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
900ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param type The type to ignore when running this transition.
901ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target type to or remove it from the
902ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded target types.
903ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
904ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
905ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(Class type, boolean exclude) {
906ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetTypeExcludes = excludeType(mTargetTypeExcludes, type, exclude);
907ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
908ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
909ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
910ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
911ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given type to the list of types whose children should
912ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * be excluded from this transition. The <code>exclude</code> parameter
913ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * specifies whether the target type should be added to or removed from
914ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the excluded list.
915ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
916ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
917ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
918ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
919ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
920ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
921ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
922ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
923ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
924ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
925ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
926ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
927ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param type The type to ignore when running this transition.
928ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target type to or remove it from the
929ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded target types.
930ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
931ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
932ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(Class type, boolean exclude) {
933ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetTypeChildExcludes = excludeType(mTargetTypeChildExcludes, type, exclude);
934ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
935ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
936ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
937ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
938ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility method to manage the boilerplate code that is the same whether we
939ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * are excluding targets or their children.
940ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
941ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    private ArrayList<Class> excludeType(ArrayList<Class> list, Class type, boolean exclude) {
942ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (type != null) {
943ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (exclude) {
944ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.add(list, type);
945ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            } else {
946ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.remove(list, type);
947ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
948ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
949ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return list;
950ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
951ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
952ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
953faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the target view instances that this Transition is interested in
954faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * animating. By default, there are no targets, and a Transition will
955faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listen for changes on every view in the hierarchy below the sceneRoot
956faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * of the Scene being transitioned into. Setting targets constrains
957faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition to only listen for, and act on, these views.
958faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * All other views will be ignored.
959faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
960ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>The target list is like the {@link #addTarget(int) targetId}
961faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * list except this list specifies the actual View instances, not the ids
962faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * of the views. This is an important distinction when scene changes involve
963faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * view hierarchies which have been inflated separately; different views may
964faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * share the same id but not actually be the same instance. If the transition
965ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should treat those views as the same, then {@link #addTarget(int)} should be used
966d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * instead of {@link #addTarget(View)}. If, on the other hand, scene changes involve
967faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * changes all within the same view hierarchy, among views which do not
968d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * necessarily have ids set on them, then the target list of views may be more
969faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * convenient.</p>
970faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
971ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #addTarget(int)
972d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param target A View on which the Transition will act, must be non-null.
973d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition to which the target is added.
974d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Returning the same object makes it easier to chain calls during
975d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * construction, such as
976d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).addTarget(someView);</code>
977d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
978d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition addTarget(View target) {
979d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        mTargets.add(target);
980d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
981d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
982d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
983d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
984d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Removes the given target from the list of targets that this Transition
985d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * is interested in animating.
986d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
987d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param target The target view, must be non-null.
988d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return Transition The Transition from which the target is removed.
989faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returning the same object makes it easier to chain calls during
990faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * construction, such as
991d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).removeTarget(someView);</code>
992faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
993d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition removeTarget(View target) {
994d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (target != null) {
995d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargets.remove(target);
996d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
997faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return this;
998faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
999faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1000faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1001faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returns the array of target IDs that this transition limits itself to
1002faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * tracking and animating. If the array is null for both this method and
1003faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * {@link #getTargets()}, then this transition is
1004faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * not limited to specific views, and will handle changes to any views
1005faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * in the hierarchy of a scene change.
1006faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1007faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @return the list of target IDs
1008faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1009d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public List<Integer> getTargetIds() {
1010faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mTargetIds;
1011faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1012faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1013faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1014faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returns the array of target views that this transition limits itself to
1015faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * tracking and animating. If the array is null for both this method and
1016faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * {@link #getTargetIds()}, then this transition is
1017faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * not limited to specific views, and will handle changes to any views
1018faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * in the hierarchy of a scene change.
1019faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1020faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @return the list of target views
1021faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1022d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public List<View> getTargets() {
1023faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mTargets;
1024faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1025faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1026faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1027faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Recursive method that captures values for the given view and the
1028faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * hierarchy underneath it.
1029faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param sceneRoot The root of the view hierarchy being captured
1030faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param start true if this capture is happening before the scene change,
1031faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * false otherwise
1032faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1033faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    void captureValues(ViewGroup sceneRoot, boolean start) {
1034df32aa87150768795816852c6393306893467ecaChet Haase        clearValues(start);
1035d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (mTargetIds.size() > 0 || mTargets.size() > 0) {
1036d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargetIds.size() > 0) {
1037d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargetIds.size(); ++i) {
1038d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    int id = mTargetIds.get(i);
1039faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    View view = sceneRoot.findViewById(id);
1040faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    if (view != null) {
1041faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        TransitionValues values = new TransitionValues();
1042faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        values.view = view;
1043d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        if (start) {
1044d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                            captureStartValues(values);
1045d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        } else {
1046d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                            captureEndValues(values);
1047d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        }
1048d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        capturePropagationValues(values);
1049faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        if (start) {
10506ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                            mStartValues.viewValues.put(view, values);
1051867a86613d4152a93423300f83597300e6ebeebeChet Haase                            if (id >= 0) {
10526ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                                mStartValues.idValues.put(id, values);
1053867a86613d4152a93423300f83597300e6ebeebeChet Haase                            }
1054faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        } else {
10556ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                            mEndValues.viewValues.put(view, values);
1056867a86613d4152a93423300f83597300e6ebeebeChet Haase                            if (id >= 0) {
10576ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                                mEndValues.idValues.put(id, values);
1058867a86613d4152a93423300f83597300e6ebeebeChet Haase                            }
1059faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        }
1060faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
1061faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1062faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1063d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargets.size() > 0) {
1064d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargets.size(); ++i) {
1065d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    View view = mTargets.get(i);
1066faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    if (view != null) {
1067faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        TransitionValues values = new TransitionValues();
1068faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        values.view = view;
1069d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        if (start) {
1070d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                            captureStartValues(values);
1071d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        } else {
1072d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                            captureEndValues(values);
1073d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        }
1074d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        capturePropagationValues(values);
1075faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        if (start) {
10766ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                            mStartValues.viewValues.put(view, values);
1077faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        } else {
10786ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                            mEndValues.viewValues.put(view, values);
1079faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        }
1080faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
1081faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1082faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1083faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1084faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            captureHierarchy(sceneRoot, start);
1085faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1086faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1087faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1088faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1089df32aa87150768795816852c6393306893467ecaChet Haase     * Clear valuesMaps for specified start/end state
1090df32aa87150768795816852c6393306893467ecaChet Haase     *
1091df32aa87150768795816852c6393306893467ecaChet Haase     * @param start true if the start values should be cleared, false otherwise
1092df32aa87150768795816852c6393306893467ecaChet Haase     */
1093df32aa87150768795816852c6393306893467ecaChet Haase    void clearValues(boolean start) {
1094df32aa87150768795816852c6393306893467ecaChet Haase        if (start) {
1095df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.viewValues.clear();
1096df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.idValues.clear();
1097df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.itemIdValues.clear();
1098df32aa87150768795816852c6393306893467ecaChet Haase        } else {
1099df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.viewValues.clear();
1100df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.idValues.clear();
1101df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.itemIdValues.clear();
1102df32aa87150768795816852c6393306893467ecaChet Haase        }
1103df32aa87150768795816852c6393306893467ecaChet Haase    }
1104df32aa87150768795816852c6393306893467ecaChet Haase
1105df32aa87150768795816852c6393306893467ecaChet Haase    /**
1106faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Recursive method which captures values for an entire view hierarchy,
1107faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * starting at some root view. Transitions without targetIDs will use this
1108faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * method to capture values for all possible views.
1109faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1110faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param view The view for which to capture values. Children of this View
1111faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * will also be captured, recursively down to the leaf nodes.
1112faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param start true if values are being captured in the start scene, false
1113faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * otherwise.
1114faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1115faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    private void captureHierarchy(View view, boolean start) {
1116faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (view == null) {
1117faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            return;
1118faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
11190a778eda690a66173733a63622886e888d405c45George Mount        if (!isValidTarget(view, view.getId())) {
11200a778eda690a66173733a63622886e888d405c45George Mount            return;
11210a778eda690a66173733a63622886e888d405c45George Mount        }
1122faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        boolean isListViewItem = false;
1123faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (view.getParent() instanceof ListView) {
1124faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            isListViewItem = true;
1125faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1126faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (isListViewItem && !((ListView) view.getParent()).getAdapter().hasStableIds()) {
1127faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            // ignore listview children unless we can track them with stable IDs
1128faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            return;
1129faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1130ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        int id = View.NO_ID;
1131ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        long itemId = View.NO_ID;
1132faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (!isListViewItem) {
1133faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            id = view.getId();
1134faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1135faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            ListView listview = (ListView) view.getParent();
1136faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            int position = listview.getPositionForView(view);
1137ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            itemId = listview.getItemIdAtPosition(position);
1138faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            view.setHasTransientState(true);
1139faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1140ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetIdExcludes != null && mTargetIdExcludes.contains(id)) {
1141ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return;
1142ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1143ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetExcludes != null && mTargetExcludes.contains(view)) {
1144ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return;
1145ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1146ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetTypeExcludes != null && view != null) {
1147ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            int numTypes = mTargetTypeExcludes.size();
1148ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            for (int i = 0; i < numTypes; ++i) {
1149ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (mTargetTypeExcludes.get(i).isInstance(view)) {
1150ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    return;
1151ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
1152ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1153ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1154e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount        if (view.getParent() instanceof ViewGroup) {
1155e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            TransitionValues values = new TransitionValues();
1156e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            values.view = view;
1157e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            if (start) {
1158e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                captureStartValues(values);
1159faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
1160e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                captureEndValues(values);
1161faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1162d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            capturePropagationValues(values);
1163e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            if (start) {
1164e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                if (!isListViewItem) {
1165e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                    mStartValues.viewValues.put(view, values);
1166e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                    if (id >= 0) {
1167e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                        mStartValues.idValues.put((int) id, values);
1168e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                    }
1169e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                } else {
1170e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                    mStartValues.itemIdValues.put(itemId, values);
1171867a86613d4152a93423300f83597300e6ebeebeChet Haase                }
1172faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
1173e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                if (!isListViewItem) {
1174e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                    mEndValues.viewValues.put(view, values);
1175e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                    if (id >= 0) {
1176e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                        mEndValues.idValues.put((int) id, values);
1177e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                    }
1178e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                } else {
1179e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                    mEndValues.itemIdValues.put(itemId, values);
1180e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                }
1181faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1182faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1183faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (view instanceof ViewGroup) {
1184ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            // Don't traverse child hierarchy if there are any child-excludes on this view
1185ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (mTargetIdChildExcludes != null && mTargetIdChildExcludes.contains(id)) {
1186ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                return;
1187ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1188ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (mTargetChildExcludes != null && mTargetChildExcludes.contains(view)) {
1189ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                return;
1190ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1191ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (mTargetTypeChildExcludes != null && view != null) {
1192ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                int numTypes = mTargetTypeChildExcludes.size();
1193ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                for (int i = 0; i < numTypes; ++i) {
1194ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    if (mTargetTypeChildExcludes.get(i).isInstance(view)) {
1195ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                        return;
1196ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    }
1197ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
1198ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1199faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            ViewGroup parent = (ViewGroup) view;
1200faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            for (int i = 0; i < parent.getChildCount(); ++i) {
1201faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                captureHierarchy(parent.getChildAt(i), start);
1202faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1203faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1204faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1205faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1206faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
12076ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * This method can be called by transitions to get the TransitionValues for
12086ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * any particular view during the transition-playing process. This might be
12096ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * necessary, for example, to query the before/after state of related views
12106ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * for a given transition.
12116ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     */
1212d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public TransitionValues getTransitionValues(View view, boolean start) {
12136ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        if (mParent != null) {
12146ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            return mParent.getTransitionValues(view, start);
12156ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        }
12166ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        TransitionValuesMaps valuesMaps = start ? mStartValues : mEndValues;
12176ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        TransitionValues values = valuesMaps.viewValues.get(view);
12186ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        if (values == null) {
12196ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            int id = view.getId();
12206ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            if (id >= 0) {
12216ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                values = valuesMaps.idValues.get(id);
12226ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            }
12236ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            if (values == null && view.getParent() instanceof ListView) {
12246ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                ListView listview = (ListView) view.getParent();
12256ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                int position = listview.getPositionForView(view);
12266ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                long itemId = listview.getItemIdAtPosition(position);
12276ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                values = valuesMaps.itemIdValues.get(itemId);
12286ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            }
12296ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            // TODO: Doesn't handle the case where a view was parented to a
12306ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            // ListView (with an itemId), but no longer is
12316ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        }
12326ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        return values;
12336ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
12346ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
12356ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    /**
1236199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Pauses this transition, sending out calls to {@link
1237199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * TransitionListener#onTransitionPause(Transition)} to all listeners
1238199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * and pausing all running animators started by this transition.
1239199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1240199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @hide
1241199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
1242cf68aad3164303df59b2a669d186a94533c9c743George Mount    public void pause(View sceneRoot) {
1243a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase        if (!mEnded) {
1244a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1245a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            int numOldAnims = runningAnimators.size();
1246cf68aad3164303df59b2a669d186a94533c9c743George Mount            WindowId windowId = sceneRoot.getWindowId();
1247a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            for (int i = numOldAnims - 1; i >= 0; i--) {
1248cf68aad3164303df59b2a669d186a94533c9c743George Mount                AnimationInfo info = runningAnimators.valueAt(i);
1249cf68aad3164303df59b2a669d186a94533c9c743George Mount                if (info.view != null && windowId.equals(info.windowId)) {
1250cf68aad3164303df59b2a669d186a94533c9c743George Mount                    Animator anim = runningAnimators.keyAt(i);
1251cf68aad3164303df59b2a669d186a94533c9c743George Mount                    anim.pause();
1252cf68aad3164303df59b2a669d186a94533c9c743George Mount                }
1253a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            }
1254a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1255a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                ArrayList<TransitionListener> tmpListeners =
1256a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1257a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                int numListeners = tmpListeners.size();
1258a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                for (int i = 0; i < numListeners; ++i) {
1259a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    tmpListeners.get(i).onTransitionPause(this);
1260a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                }
1261199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1262a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mPaused = true;
1263199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1264199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1265199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1266199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1267199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Resumes this transition, sending out calls to {@link
1268199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * TransitionListener#onTransitionPause(Transition)} to all listeners
1269199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * and pausing all running animators started by this transition.
1270199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1271199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @hide
1272199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
1273cf68aad3164303df59b2a669d186a94533c9c743George Mount    public void resume(View sceneRoot) {
1274199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (mPaused) {
1275a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            if (!mEnded) {
1276a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1277a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                int numOldAnims = runningAnimators.size();
1278cf68aad3164303df59b2a669d186a94533c9c743George Mount                WindowId windowId = sceneRoot.getWindowId();
1279a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                for (int i = numOldAnims - 1; i >= 0; i--) {
1280cf68aad3164303df59b2a669d186a94533c9c743George Mount                    AnimationInfo info = runningAnimators.valueAt(i);
1281cf68aad3164303df59b2a669d186a94533c9c743George Mount                    if (info.view != null && windowId.equals(info.windowId)) {
1282cf68aad3164303df59b2a669d186a94533c9c743George Mount                        Animator anim = runningAnimators.keyAt(i);
1283cf68aad3164303df59b2a669d186a94533c9c743George Mount                        anim.resume();
1284cf68aad3164303df59b2a669d186a94533c9c743George Mount                    }
1285a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                }
1286a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                if (mListeners != null && mListeners.size() > 0) {
1287a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    ArrayList<TransitionListener> tmpListeners =
1288a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                            (ArrayList<TransitionListener>) mListeners.clone();
1289a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    int numListeners = tmpListeners.size();
1290a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    for (int i = 0; i < numListeners; ++i) {
1291a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                        tmpListeners.get(i).onTransitionResume(this);
1292a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    }
1293199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                }
1294199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1295199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            mPaused = false;
1296199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1297199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1298199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1299199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1300faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Called by TransitionManager to play the transition. This calls
1301d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * createAnimators() to set things up and create all of the animations and then
13022ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * runAnimations() to actually start the animations.
1303faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
13046ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    void playTransition(ViewGroup sceneRoot) {
1305199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1306199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        int numOldAnims = runningAnimators.size();
1307199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        for (int i = numOldAnims - 1; i >= 0; i--) {
1308199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            Animator anim = runningAnimators.keyAt(i);
1309199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            if (anim != null) {
1310199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                AnimationInfo oldInfo = runningAnimators.get(anim);
131158ad12208afcf9fdce735dead8449c4db375344dChet Haase                if (oldInfo != null && oldInfo.view != null &&
131258ad12208afcf9fdce735dead8449c4db375344dChet Haase                        oldInfo.view.getContext() == sceneRoot.getContext()) {
1313199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    boolean cancel = false;
1314199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    TransitionValues oldValues = oldInfo.values;
1315199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    View oldView = oldInfo.view;
1316199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    TransitionValues newValues = mEndValues.viewValues != null ?
1317199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            mEndValues.viewValues.get(oldView) : null;
131823c61f6bc57a611d97d333bce0d8fe00ab81af4cChet Haase                    if (newValues == null) {
131923c61f6bc57a611d97d333bce0d8fe00ab81af4cChet Haase                        newValues = mEndValues.idValues.get(oldView.getId());
132023c61f6bc57a611d97d333bce0d8fe00ab81af4cChet Haase                    }
1321af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                    if (oldValues != null) {
1322af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                        // if oldValues null, then transition didn't care to stash values,
1323af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                        // and won't get canceled
132423c61f6bc57a611d97d333bce0d8fe00ab81af4cChet Haase                        if (newValues != null) {
1325af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                            for (String key : oldValues.values.keySet()) {
1326af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                Object oldValue = oldValues.values.get(key);
1327af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                Object newValue = newValues.values.get(key);
1328af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                if (oldValue != null && newValue != null &&
1329af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                        !oldValue.equals(newValue)) {
1330af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                    cancel = true;
1331af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                    if (DBG) {
1332af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                        Log.d(LOG_TAG, "Transition.playTransition: " +
1333af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                                "oldValue != newValue for " + key +
1334af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                                ": old, new = " + oldValue + ", " + newValue);
1335af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                    }
1336af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                    break;
1337199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                }
1338199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
1339199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
1340199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    }
1341199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    if (cancel) {
1342199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        if (anim.isRunning() || anim.isStarted()) {
1343199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            if (DBG) {
1344199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                Log.d(LOG_TAG, "Canceling anim " + anim);
1345199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
1346199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            anim.cancel();
1347199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        } else {
1348199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            if (DBG) {
1349199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                Log.d(LOG_TAG, "removing anim from info list: " + anim);
1350199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
1351199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            runningAnimators.remove(anim);
1352199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
1353199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    }
1354199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                }
1355199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1356199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1357199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1358d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        createAnimators(sceneRoot, mStartValues, mEndValues);
1359d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        runAnimators();
1360faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1361faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1362faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1363faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This is a utility method used by subclasses to handle standard parts of
1364faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * setting up and running an Animator: it sets the {@link #getDuration()
1365faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * duration} and the {@link #getStartDelay() startDelay}, starts the
1366199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animation, and, when the animator ends, calls {@link #end()}.
1367faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1368faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param animator The Animator to be run during this transition.
1369faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1370faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1371faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1372faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    protected void animate(Animator animator) {
1373faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        // TODO: maybe pass auto-end as a boolean parameter?
1374faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (animator == null) {
1375199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            end();
1376faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1377faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getDuration() >= 0) {
1378faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                animator.setDuration(getDuration());
1379faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1380faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getStartDelay() >= 0) {
1381d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                animator.setStartDelay(getStartDelay() + animator.getStartDelay());
1382faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1383faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getInterpolator() != null) {
1384faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                animator.setInterpolator(getInterpolator());
1385faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1386faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            animator.addListener(new AnimatorListenerAdapter() {
1387faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                @Override
1388faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                public void onAnimationEnd(Animator animation) {
1389199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    end();
1390faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    animation.removeListener(this);
1391faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1392faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            });
1393faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            animator.start();
1394faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1395faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1396faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1397faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1398faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method is called automatically by the transition and
1399d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * TransitionSet classes prior to a Transition subclass starting;
1400faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * subclasses should not need to call it directly.
1401faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1402faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1403faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1404199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void start() {
1405faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mNumInstances == 0) {
1406faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1407faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                ArrayList<TransitionListener> tmpListeners =
1408faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1409faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                int numListeners = tmpListeners.size();
1410faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                for (int i = 0; i < numListeners; ++i) {
1411faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    tmpListeners.get(i).onTransitionStart(this);
1412faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1413faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1414a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mEnded = false;
1415faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1416faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mNumInstances++;
1417faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1418faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1419faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1420faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method is called automatically by the Transition and
1421d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * TransitionSet classes when a transition finishes, either because
1422faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * a transition did nothing (returned a null Animator from
1423d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link Transition#createAnimator(ViewGroup, TransitionValues,
1424faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * TransitionValues)}) or because the transition returned a valid
1425199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Animator and end() was called in the onAnimationEnd()
1426faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * callback of the AnimatorListener.
1427faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1428faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1429faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1430199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void end() {
1431faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        --mNumInstances;
1432faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mNumInstances == 0) {
1433faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1434faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                ArrayList<TransitionListener> tmpListeners =
1435faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1436faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                int numListeners = tmpListeners.size();
1437faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                for (int i = 0; i < numListeners; ++i) {
1438faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    tmpListeners.get(i).onTransitionEnd(this);
1439faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1440faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
14416ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            for (int i = 0; i < mStartValues.itemIdValues.size(); ++i) {
14426ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues tv = mStartValues.itemIdValues.valueAt(i);
1443faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                View v = tv.view;
1444faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                if (v.hasTransientState()) {
1445faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    v.setHasTransientState(false);
1446faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1447faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
14486ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            for (int i = 0; i < mEndValues.itemIdValues.size(); ++i) {
14496ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues tv = mEndValues.itemIdValues.valueAt(i);
1450faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                View v = tv.view;
1451faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                if (v.hasTransientState()) {
1452faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    v.setHasTransientState(false);
1453faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1454faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1455a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mEnded = true;
1456faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1457faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1458faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1459faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1460faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method cancels a transition that is currently running.
1461d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
1462d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @hide
1463faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1464199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void cancel() {
1465e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        int numAnimators = mCurrentAnimators.size();
146625a738fb257aacfc87d3363a834ed6e0b050c3b1Chet Haase        for (int i = numAnimators - 1; i >= 0; i--) {
1467e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            Animator animator = mCurrentAnimators.get(i);
1468e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animator.cancel();
1469e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        }
1470faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners != null && mListeners.size() > 0) {
1471faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            ArrayList<TransitionListener> tmpListeners =
1472faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    (ArrayList<TransitionListener>) mListeners.clone();
1473faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            int numListeners = tmpListeners.size();
1474faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            for (int i = 0; i < numListeners; ++i) {
1475faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                tmpListeners.get(i).onTransitionCancel(this);
1476faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1477faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1478faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1479faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1480faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1481faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Adds a listener to the set of listeners that are sent events through the
1482faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * life of an animation, such as start, repeat, and end.
1483faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1484faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param listener the listener to be added to the current set of listeners
1485faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * for this animation.
1486d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
1487faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1488d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition addListener(TransitionListener listener) {
1489faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners == null) {
1490faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            mListeners = new ArrayList<TransitionListener>();
1491faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1492faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mListeners.add(listener);
1493d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
1494faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1495faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1496faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1497faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Removes a listener from the set listening to this animation.
1498faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1499faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param listener the listener to be removed from the current set of
1500faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listeners for this transition.
1501d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
1502faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1503d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition removeListener(TransitionListener listener) {
1504faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners == null) {
1505d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            return this;
1506faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1507faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mListeners.remove(listener);
1508faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners.size() == 0) {
1509faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            mListeners = null;
1510faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1511d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
1512faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1513faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1514d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1515d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Sets the callback to use to find the epicenter of a Transition. A null value indicates
1516d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * that there is no epicenter in the Transition and getEpicenter() will return null.
1517d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Transitions like {@link android.transition.Explode} use a point or Rect to orient
1518d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the direction of travel. This is called the epicenter of the Transition and is
1519d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * typically centered on a touched View. The
1520d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
1521d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * dynamically retrieve the epicenter during a Transition.
1522d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param epicenterCallback The callback to use to find the epicenter of the Transition.
1523d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1524d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public void setEpicenterCallback(EpicenterCallback epicenterCallback) {
1525d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        mEpicenterCallback = epicenterCallback;
1526d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1527d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1528d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1529d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Returns the callback used to find the epicenter of the Transition.
1530d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Transitions like {@link android.transition.Explode} use a point or Rect to orient
1531d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the direction of travel. This is called the epicenter of the Transition and is
1532d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * typically centered on a touched View. The
1533d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
1534d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * dynamically retrieve the epicenter during a Transition.
1535d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return the callback used to find the epicenter of the Transition.
1536d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1537d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public EpicenterCallback getEpicenterCallback() {
1538d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        return mEpicenterCallback;
1539d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1540d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1541d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1542d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Returns the epicenter as specified by the
1543d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
1544d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return the epicenter as specified by the
1545d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
1546d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @see #setEpicenterCallback(android.transition.Transition.EpicenterCallback)
1547d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1548d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public Rect getEpicenter() {
1549d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (mEpicenterCallback == null) {
1550d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            return null;
1551d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
1552d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        return mEpicenterCallback.getEpicenter(this);
1553d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1554d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1555d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1556d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Sets the method for determining Animator start delays.
1557d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * When a Transition affects several Views like {@link android.transition.Explode} or
1558d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
1559d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * such that the Animator start delay depends on position of the View. The
1560d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * TransitionPropagation specifies how the start delays are calculated.
1561d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param transitionPropagation The class used to determine the start delay of
1562d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *                              Animators created by this Transition. A null value
1563d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *                              indicates that no delay should be used.
1564d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1565d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public void setPropagation(TransitionPropagation transitionPropagation) {
1566d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        mPropagation = transitionPropagation;
1567d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1568d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1569d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1570d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Returns the {@link android.transition.TransitionPropagation} used to calculate Animator start
1571d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * delays.
1572d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * When a Transition affects several Views like {@link android.transition.Explode} or
1573d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
1574d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * such that the Animator start delay depends on position of the View. The
1575d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * TransitionPropagation specifies how the start delays are calculated.
1576d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return the {@link android.transition.TransitionPropagation} used to calculate Animator start
1577d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * delays. This is null by default.
1578d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1579d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public TransitionPropagation getPropagation() {
1580d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        return mPropagation;
1581d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1582d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1583d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1584d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Captures TransitionPropagation values for the given view and the
1585d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * hierarchy underneath it.
1586d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1587d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    void capturePropagationValues(TransitionValues transitionValues) {
158831a217290cf376d0573fc36e21c8940987485019George Mount        if (mPropagation != null && !transitionValues.values.isEmpty()) {
1589d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            String[] propertyNames = mPropagation.getPropagationProperties();
1590d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (propertyNames == null) {
1591d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                return;
1592d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
1593d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            boolean containsAll = true;
1594d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            for (int i = 0; i < propertyNames.length; i++) {
1595d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                if (!transitionValues.values.containsKey(propertyNames[i])) {
1596d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    containsAll = false;
1597d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    break;
1598d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                }
1599d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
1600d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (!containsAll) {
1601d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                mPropagation.captureValues(transitionValues);
1602d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
1603d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
1604d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1605d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1606d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    Transition setSceneRoot(ViewGroup sceneRoot) {
16076ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        mSceneRoot = sceneRoot;
1608d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
16096ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
16106ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
1611b7a7fc9d233bad507ce893882352618b13647058Chet Haase    void setCanRemoveViews(boolean canRemoveViews) {
1612b7a7fc9d233bad507ce893882352618b13647058Chet Haase        mCanRemoveViews = canRemoveViews;
1613b7a7fc9d233bad507ce893882352618b13647058Chet Haase    }
1614b7a7fc9d233bad507ce893882352618b13647058Chet Haase
16150a778eda690a66173733a63622886e888d405c45George Mount    public boolean canRemoveViews() {
16160a778eda690a66173733a63622886e888d405c45George Mount        return mCanRemoveViews;
16170a778eda690a66173733a63622886e888d405c45George Mount    }
16180a778eda690a66173733a63622886e888d405c45George Mount
1619faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    @Override
1620faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public String toString() {
1621faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return toString("");
1622faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1623faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
16246ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    @Override
16256ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    public Transition clone() {
16266ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        Transition clone = null;
16276ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        try {
16286ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            clone = (Transition) super.clone();
1629199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            clone.mAnimators = new ArrayList<Animator>();
16307660d121b2ef21164ed33e6091e5dd50f5d0f939Chet Haase            clone.mStartValues = new TransitionValuesMaps();
16317660d121b2ef21164ed33e6091e5dd50f5d0f939Chet Haase            clone.mEndValues = new TransitionValuesMaps();
16326ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        } catch (CloneNotSupportedException e) {}
16336ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
16346ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        return clone;
16356ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
16366ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
1637199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1638199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the name of this Transition. This name is used internally to distinguish
1639199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * between different transitions to determine when interrupting transitions overlap.
1640d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * For example, a ChangeBounds running on the same target view as another ChangeBounds
1641d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * should determine whether the old transition is animating to different end values
1642d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * and should be canceled in favor of the new transition.
1643199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1644199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * <p>By default, a Transition's name is simply the value of {@link Class#getName()},
1645199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * but subclasses are free to override and return something different.</p>
1646199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1647199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return The name of this transition.
1648199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
1649199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public String getName() {
1650199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return mName;
1651199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1652199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1653faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    String toString(String indent) {
1654faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        String result = indent + getClass().getSimpleName() + "@" +
1655faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                Integer.toHexString(hashCode()) + ": ";
1656c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mDuration != -1) {
1657c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "dur(" + mDuration + ") ";
1658c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
1659c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mStartDelay != -1) {
1660c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "dly(" + mStartDelay + ") ";
1661c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
1662c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mInterpolator != null) {
1663c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "interp(" + mInterpolator + ") ";
1664c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
1665d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (mTargetIds.size() > 0 || mTargets.size() > 0) {
1666c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "tgts(";
1667d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargetIds.size() > 0) {
1668d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargetIds.size(); ++i) {
1669c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (i > 0) {
1670c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        result += ", ";
1671c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
1672d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    result += mTargetIds.get(i);
1673faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1674faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1675d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargets.size() > 0) {
1676d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargets.size(); ++i) {
1677c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (i > 0) {
1678c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        result += ", ";
1679c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
1680d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    result += mTargets.get(i);
1681faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1682faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1683c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += ")";
1684faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1685faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return result;
1686faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1687faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1688faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1689faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * A transition listener receives notifications from a transition.
1690199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Notifications indicate transition lifecycle events.
1691faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1692faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public static interface TransitionListener {
1693faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
1694faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the start of the transition.
1695faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
1696faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The started transition.
1697faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
1698faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionStart(Transition transition);
1699faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1700faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
1701faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the end of the transition. Canceled transitions
1702faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * will always notify listeners of both the cancellation and end
1703199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * events. That is, {@link #onTransitionEnd(Transition)} is always called,
1704faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * regardless of whether the transition was canceled or played
1705faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * through to completion.
1706faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
1707faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The transition which reached its end.
1708faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
1709faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionEnd(Transition transition);
1710faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1711faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
1712faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the cancellation of the transition.
1713d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that cancel may be called by a parent {@link TransitionSet} on
1714199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
1715199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state on target objects which was set at
1716d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
1717d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * createAnimator()} time.
1718faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
1719faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The transition which was canceled.
1720faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
1721faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionCancel(Transition transition);
1722199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1723199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        /**
1724199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * Notification when a transition is paused.
1725d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that createAnimator() may be called by a parent {@link TransitionSet} on
1726199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
1727199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state on target objects which was set at
1728d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
1729d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * createAnimator()} time.
1730199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         *
1731199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * @param transition The transition which was paused.
1732199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         */
1733199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        void onTransitionPause(Transition transition);
1734199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1735199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        /**
1736199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * Notification when a transition is resumed.
1737d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that resume() may be called by a parent {@link TransitionSet} on
1738199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
1739199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state which may have changed in an earlier call
1740199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * to {@link #onTransitionPause(Transition)}.
1741199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         *
1742199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * @param transition The transition which was resumed.
1743199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         */
1744199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        void onTransitionResume(Transition transition);
1745faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1746faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1747faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1748faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Utility adapter class to avoid having to override all three methods
1749faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * whenever someone just wants to listen for a single event.
1750faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1751faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1752faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * */
1753faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public static class TransitionListenerAdapter implements TransitionListener {
1754faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
1755faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionStart(Transition transition) {
1756faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1757faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1758faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
1759faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionEnd(Transition transition) {
1760faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1761faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1762faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
1763faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionCancel(Transition transition) {
1764faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1765199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1766199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        @Override
1767199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        public void onTransitionPause(Transition transition) {
1768199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1769199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1770199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        @Override
1771199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        public void onTransitionResume(Transition transition) {
1772199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1773faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1774faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1775199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1776199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Holds information about each animator used when a new transition starts
1777199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * while other transitions are still running to determine whether a running
1778199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animation should be canceled or a new animation noop'd. The structure holds
1779199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * information about the state that an animation is going to, to be compared to
1780199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * end state of a new animation.
17810a778eda690a66173733a63622886e888d405c45George Mount     * @hide
1782199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
17830a778eda690a66173733a63622886e888d405c45George Mount    public static class AnimationInfo {
17840a778eda690a66173733a63622886e888d405c45George Mount        public View view;
1785199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        String name;
1786199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        TransitionValues values;
1787cf68aad3164303df59b2a669d186a94533c9c743George Mount        WindowId windowId;
1788199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1789cf68aad3164303df59b2a669d186a94533c9c743George Mount        AnimationInfo(View view, String name, WindowId windowId, TransitionValues values) {
1790199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.view = view;
1791199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.name = name;
1792199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.values = values;
1793cf68aad3164303df59b2a669d186a94533c9c743George Mount            this.windowId = windowId;
1794199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1795199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1796ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1797ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1798ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility class for managing typed ArrayLists efficiently. In particular, this
1799ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * can be useful for lists that we don't expect to be used often (eg, the exclude
1800ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * lists), so we'd like to keep them nulled out by default. This causes the code to
1801ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * become tedious, with constant null checks, code to allocate when necessary,
1802ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * and code to null out the reference when the list is empty. This class encapsulates
1803ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * all of that functionality into simple add()/remove() methods which perform the
1804ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * necessary checks, allocation/null-out as appropriate, and return the
1805ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * resulting list.
1806ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1807ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    private static class ArrayListManager {
1808ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1809ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        /**
1810ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Add the specified item to the list, returning the resulting list.
1811ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * The returned list can either the be same list passed in or, if that
1812ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list was null, the new list that was created.
1813ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         *
1814ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Note that the list holds unique items; if the item already exists in the
1815ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list, the list is not modified.
1816ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         */
1817ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        static <T> ArrayList<T> add(ArrayList<T> list, T item) {
1818ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (list == null) {
1819ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = new ArrayList<T>();
1820ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1821ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (!list.contains(item)) {
1822ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list.add(item);
1823ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1824ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return list;
1825ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1826ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1827ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        /**
1828ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Remove the specified item from the list, returning the resulting list.
1829ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * The returned list can either the be same list passed in or, if that
1830ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list becomes empty as a result of the remove(), the new list was created.
1831ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         */
1832ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        static <T> ArrayList<T> remove(ArrayList<T> list, T item) {
1833ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (list != null) {
1834ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list.remove(item);
1835ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (list.isEmpty()) {
1836ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    list = null;
1837ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
1838ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1839ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return list;
1840ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1841ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1842ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1843d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1844d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Class to get the epicenter of Transition. Use
1845d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #setEpicenterCallback(android.transition.Transition.EpicenterCallback)} to
1846d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * set the callback used to calculate the epicenter of the Transition. Override
1847d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #getEpicenter()} to return the rectangular region in screen coordinates of
1848d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the epicenter of the transition.
1849d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @see #setEpicenterCallback(android.transition.Transition.EpicenterCallback)
1850d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1851d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public static abstract class EpicenterCallback {
1852d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1853d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        /**
1854d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * Implementers must override to return the epicenter of the Transition in screen
1855d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * coordinates. Transitions like {@link android.transition.Explode} depend upon
1856d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * an epicenter for the Transition. In Explode, Views move toward or away from the
1857d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * center of the epicenter Rect along the vector between the epicenter and the center
1858d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * of the View appearing and disappearing. Some Transitions, such as
1859d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * {@link android.transition.Fade} pay no attention to the epicenter.
1860d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         *
1861d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * @param transition The transition for which the epicenter applies.
1862d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * @return The Rect region of the epicenter of <code>transition</code> or null if
1863d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * there is no epicenter.
1864d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         */
1865d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        public abstract Rect getEpicenter(Transition transition);
1866d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1867faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase}
1868