Transition.java revision 0a778eda690a66173733a63622886e888d405c45
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;
2208735185f8105710e18ad02297461bec9268e514Chet Haaseimport android.util.ArrayMap;
23c43524f3869cc0d36974fce61986017093f2ecd2Chet Haaseimport android.util.Log;
24faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.util.LongSparseArray;
25faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.util.SparseArray;
26faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.SurfaceView;
27faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.TextureView;
28faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.View;
29faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.ViewGroup;
30faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.ViewOverlay;
31faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.widget.ListView;
32ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haaseimport android.widget.Spinner;
33faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
34faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport java.util.ArrayList;
35d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haaseimport java.util.List;
36faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
37faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/**
38faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * A Transition holds information about animations that will be run on its
39faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * targets during a scene change. Subclasses of this abstract class may
40d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * choreograph several child transitions ({@link TransitionSet} or they may
41faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * perform custom animations themselves. Any Transition has two main jobs:
42faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * (1) capture property values, and (2) play animations based on changes to
43faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * captured property values. A custom transition knows what property values
44faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * on View objects are of interest to it, and also knows how to animate
45faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * changes to those values. For example, the {@link Fade} transition tracks
46faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * changes to visibility-related properties and is able to construct and run
47faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * animations that fade items in or out based on changes to those properties.
48faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase *
49faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * <p>Note: Transitions may not work correctly with either {@link SurfaceView}
50faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * or {@link TextureView}, due to the way that these views are displayed
51faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * on the screen. For SurfaceView, the problem is that the view is updated from
52faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * a non-UI thread, so changes to the view due to transitions (such as moving
53faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * and resizing the view) may be out of sync with the display inside those bounds.
54faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * TextureView is more compatible with transitions in general, but some
55d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * specific transitions (such as {@link Fade}) may not be compatible
56faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * with TextureView because they rely on {@link ViewOverlay} functionality,
57faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * which does not currently work with TextureView.</p>
58d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
59d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * <p>Transitions can be declared in XML resource files inside the <code>res/transition</code>
60d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * directory. Transition resources consist of a tag name for one of the Transition
61d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * subclasses along with attributes to define some of the attributes of that transition.
62d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * For example, here is a minimal resource file that declares a {@link ChangeBounds} transition:</p>
63d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
64d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@sample development/samples/ApiDemos/res/transition/changebounds.xml ChangeBounds}
65d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
66d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * <p>Note that attributes for the transition are not required, just as they are
67d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * optional when declared in code; Transitions created from XML resources will use
68d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * the same defaults as their code-created equivalents. Here is a slightly more
69d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * elaborate example which declares a {@link TransitionSet} transition with
70d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link ChangeBounds} and {@link Fade} child transitions:</p>
71d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
72d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@sample
73d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * development/samples/ApiDemos/res/transition/changebounds_fadeout_sequential.xml TransitionSet}
74d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
75d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * <p>In this example, the transitionOrdering attribute is used on the TransitionSet
76d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * object to change from the default {@link TransitionSet#ORDERING_TOGETHER} behavior
77d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * to be {@link TransitionSet#ORDERING_SEQUENTIAL} instead. Also, the {@link Fade}
78d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * transition uses a fadingMode of {@link Fade#OUT} instead of the default
79d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * out-in behavior. Finally, note the use of the <code>targets</code> sub-tag, which
80d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * takes a set of {@link android.R.styleable#TransitionTarget target} tags, each
81d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * of which lists a specific <code>targetId</code> which this transition acts upon.
82d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * Use of targets is optional, but can be used to either limit the time spent checking
83d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * attributes on unchanging views, or limiting the types of animations run on specific views.
84d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * In this case, we know that only the <code>grayscaleContainer</code> will be
85d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * disappearing, so we choose to limit the {@link Fade} transition to only that view.</p>
86d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
87d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * Further information on XML resource descriptions for transitions can be found for
88d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link android.R.styleable#Transition}, {@link android.R.styleable#TransitionSet},
89d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link android.R.styleable#TransitionTarget}, and {@link android.R.styleable#Fade}.
90d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
91faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */
926ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haasepublic abstract class Transition implements Cloneable {
93faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
94faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    private static final String LOG_TAG = "Transition";
95faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    static final boolean DBG = false;
96faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
97199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    private String mName = getClass().getName();
98199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
99faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    long mStartDelay = -1;
100faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    long mDuration = -1;
101faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    TimeInterpolator mInterpolator = null;
102d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    ArrayList<Integer> mTargetIds = new ArrayList<Integer>();
103d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    ArrayList<View> mTargets = new ArrayList<View>();
104ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Integer> mTargetIdExcludes = null;
105ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<View> mTargetExcludes = null;
106ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Class> mTargetTypeExcludes = null;
107ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Integer> mTargetIdChildExcludes = null;
108ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<View> mTargetChildExcludes = null;
109ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Class> mTargetTypeChildExcludes = null;
1106ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    private TransitionValuesMaps mStartValues = new TransitionValuesMaps();
1116ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    private TransitionValuesMaps mEndValues = new TransitionValuesMaps();
112d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    TransitionSet mParent = null;
1136ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
114199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    // Per-animator information used for later canceling when future transitions overlap
115199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    private static ThreadLocal<ArrayMap<Animator, AnimationInfo>> sRunningAnimators =
116199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            new ThreadLocal<ArrayMap<Animator, AnimationInfo>>();
117199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
118d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    // Scene Root is set at createAnimator() time in the cloned Transition
1196ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    ViewGroup mSceneRoot = null;
1206ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
121b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // Whether removing views from their parent is possible. This is only for views
122b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // in the start scene, which are no longer in the view hierarchy. This property
123b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // is determined by whether the previous Scene was created from a layout
124b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // resource, and thus the views from the exited scene are going away anyway
125b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // and can be removed as necessary to achieve a particular effect, such as
126b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // removing them from parents to add them to overlays.
127b7a7fc9d233bad507ce893882352618b13647058Chet Haase    boolean mCanRemoveViews = false;
128b7a7fc9d233bad507ce893882352618b13647058Chet Haase
129e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    // Track all animators in use in case the transition gets canceled and needs to
130e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    // cancel running animators
131e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    private ArrayList<Animator> mCurrentAnimators = new ArrayList<Animator>();
132e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase
133faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    // Number of per-target instances of this Transition currently running. This count is
134199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    // determined by calls to start() and end()
135faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    int mNumInstances = 0;
136faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
137199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    // Whether this transition is currently paused, due to a call to pause()
138199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    boolean mPaused = false;
139c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase
140a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase    // Whether this transition has ended. Used to avoid pause/resume on transitions
141a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase    // that have completed
142a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase    private boolean mEnded = false;
143a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase
144c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase    // The set of listeners to be sent transition lifecycle events.
145faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    ArrayList<TransitionListener> mListeners = null;
146faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
147d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    // The set of animators collected from calls to createAnimator(),
148d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    // to be run in runAnimators()
149199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    ArrayList<Animator> mAnimators = new ArrayList<Animator>();
150c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase
151faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
152faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Constructs a Transition object with no target objects. A transition with
153faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * no targets defaults to running on all target objects in the scene hierarchy
154d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * (if the transition is not contained in a TransitionSet), or all target
155d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * objects passed down from its parent (if it is in a TransitionSet).
156faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
157faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public Transition() {}
158faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
159faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
160faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the duration of this transition. By default, there is no duration
161faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * (indicated by a negative number), which means that the Animator created by
162faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the transition will have its own specified duration. If the duration of a
163faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Transition is set, that duration will override the Animator duration.
164faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
165faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param duration The length of the animation, in milliseconds.
166faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @return This transition object.
167d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @attr ref android.R.styleable#Transition_duration
168faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
169faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public Transition setDuration(long duration) {
170faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mDuration = duration;
171faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return this;
172faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
173faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
174199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
175199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the duration set on this transition. If no duration has been set,
176199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the returned value will be negative, indicating that resulting animators will
177199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * retain their own durations.
178199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
179d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The duration set on this transition, in milliseconds, if one has been
180d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * set, otherwise returns a negative number.
181199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
182faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public long getDuration() {
183faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mDuration;
184faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
185faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
186faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
187faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the startDelay of this transition. By default, there is no delay
188faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * (indicated by a negative number), which means that the Animator created by
189faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the transition will have its own specified startDelay. If the delay of a
190faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Transition is set, that delay will override the Animator delay.
191faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
192faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param startDelay The length of the delay, in milliseconds.
193d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
194d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @attr ref android.R.styleable#Transition_startDelay
195faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
196d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition setStartDelay(long startDelay) {
197faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mStartDelay = startDelay;
198d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
199faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
200faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
201199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
202199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the startDelay set on this transition. If no startDelay has been set,
203199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the returned value will be negative, indicating that resulting animators will
204199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * retain their own startDelays.
205199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
206d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The startDelay set on this transition, in milliseconds, if one has
207d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * been set, otherwise returns a negative number.
208199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
209faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public long getStartDelay() {
210faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mStartDelay;
211faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
212faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
213faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
214faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the interpolator of this transition. By default, the interpolator
215faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * is null, which means that the Animator created by the transition
216faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * will have its own specified interpolator. If the interpolator of a
217faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Transition is set, that interpolator will override the Animator interpolator.
218faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
219faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param interpolator The time interpolator used by the transition
220d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
221d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @attr ref android.R.styleable#Transition_interpolator
222faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
223d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition setInterpolator(TimeInterpolator interpolator) {
224faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mInterpolator = interpolator;
225d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
226faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
227faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
228199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
229199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the interpolator set on this transition. If no interpolator has been set,
230199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the returned value will be null, indicating that resulting animators will
231199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * retain their own interpolators.
232199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
233199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return The interpolator set on this transition, if one has been set, otherwise
234199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * returns null.
235199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
236faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public TimeInterpolator getInterpolator() {
237faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mInterpolator;
238faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
239faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
240faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
241199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the set of property names used stored in the {@link TransitionValues}
242d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * object passed into {@link #captureStartValues(TransitionValues)} that
243199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * this transition cares about for the purposes of canceling overlapping animations.
244199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * When any transition is started on a given scene root, all transitions
245199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * currently running on that same scene root are checked to see whether the
246199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * properties on which they based their animations agree with the end values of
247199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the same properties in the new transition. If the end values are not equal,
248199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * then the old animation is canceled since the new transition will start a new
249199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animation to these new values. If the values are equal, the old animation is
250199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * allowed to continue and no new animation is started for that transition.
251199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
252199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * <p>A transition does not need to override this method. However, not doing so
253199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * will mean that the cancellation logic outlined in the previous paragraph
254199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * will be skipped for that transition, possibly leading to artifacts as
255199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * old transitions and new transitions on the same targets run in parallel,
256199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animating views toward potentially different end values.</p>
257199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
258199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return An array of property names as described in the class documentation for
259199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * {@link TransitionValues}. The default implementation returns <code>null</code>.
260199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
261199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public String[] getTransitionProperties() {
262199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return null;
263199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
264199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
265199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
266d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * This method creates an animation that will be run for this transition
267d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * given the information in the startValues and endValues structures captured
268d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * earlier for the start and end scenes. Subclasses of Transition should override
269d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * this method. The method should only be called by the transition system; it is
270d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * not intended to be called from external classes.
271d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
272d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>This method is called by the transition's parent (all the way up to the
273faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * topmost Transition in the hierarchy) with the sceneRoot and start/end
2742ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * values that the transition may need to set up initial target values
2752ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * and construct an appropriate animation. For example, if an overall
276d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Transition is a {@link TransitionSet} consisting of several
277faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * child transitions in sequence, then some of the child transitions may
278faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * want to set initial values on target views prior to the overall
2792ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * Transition commencing, to put them in an appropriate state for the
280faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * delay between that start and the child Transition start time. For
281faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * example, a transition that fades an item in may wish to set the starting
282faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * alpha value to 0, to avoid it blinking in prior to the transition
283faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * actually starting the animation. This is necessary because the scene
284faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * change that triggers the Transition will automatically set the end-scene
285faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * on all target views, so a Transition that wants to animate from a
286d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * different value should set that value prior to returning from this method.</p>
287faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
288faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * <p>Additionally, a Transition can perform logic to determine whether
289faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the transition needs to run on the given target and start/end values.
290faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * For example, a transition that resizes objects on the screen may wish
291faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * to avoid running for views which are not present in either the start
292d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * or end scenes.</p>
2932ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     *
2942ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * <p>If there is an animator created and returned from this method, the
2952ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * transition mechanism will apply any applicable duration, startDelay,
2962ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * and interpolator to that animation and start it. A return value of
2972ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * <code>null</code> indicates that no animation should run. The default
2982ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * implementation returns null.</p>
299faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
300faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * <p>The method is called for every applicable target object, which is
301faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * stored in the {@link TransitionValues#view} field.</p>
302faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
303d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
304d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param sceneRoot The root of the transition hierarchy.
305d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param startValues The values for a specific target in the start scene.
306d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param endValues The values for the target in the end scene.
307d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return A Animator to be started at the appropriate time in the
308d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * overall transition for this scene change. A null value means no animation
309d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * should be run.
310faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
311d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
312faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues endValues) {
3132ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase        return null;
314faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
315faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
316faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
317d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * This method, essentially a wrapper around all calls to createAnimator for all
318d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * possible target views, is called with the entire set of start/end
319faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * values. The implementation in Transition iterates through these lists
320d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * and calls {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}
321faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * with each set of start/end values on this transition. The
322d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * TransitionSet subclass overrides this method and delegates it to
3232ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * each of its children in succession.
324faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
325faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
326faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
327d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
3286ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValuesMaps endValues) {
329c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (DBG) {
330d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            Log.d(LOG_TAG, "createAnimators() for " + this);
331c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
3326ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        ArrayMap<View, TransitionValues> endCopy =
3336ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                new ArrayMap<View, TransitionValues>(endValues.viewValues);
334faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        SparseArray<TransitionValues> endIdCopy =
3356ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                new SparseArray<TransitionValues>(endValues.idValues.size());
3366ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        for (int i = 0; i < endValues.idValues.size(); ++i) {
3376ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            int id = endValues.idValues.keyAt(i);
3386ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            endIdCopy.put(id, endValues.idValues.valueAt(i));
339faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
340faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        LongSparseArray<TransitionValues> endItemIdCopy =
3416ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                new LongSparseArray<TransitionValues>(endValues.itemIdValues.size());
3426ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        for (int i = 0; i < endValues.itemIdValues.size(); ++i) {
3436ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            long id = endValues.itemIdValues.keyAt(i);
3446ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            endItemIdCopy.put(id, endValues.itemIdValues.valueAt(i));
345faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
346faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        // Walk through the start values, playing everything we find
347faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        // Remove from the end set as we go
348faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        ArrayList<TransitionValues> startValuesList = new ArrayList<TransitionValues>();
349faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        ArrayList<TransitionValues> endValuesList = new ArrayList<TransitionValues>();
3506ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        for (View view : startValues.viewValues.keySet()) {
351faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues start = null;
352faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues end = null;
353faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            boolean isInListView = false;
354faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (view.getParent() instanceof ListView) {
355faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                isInListView = true;
356faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
357faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (!isInListView) {
358faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                int id = view.getId();
3596ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                start = startValues.viewValues.get(view) != null ?
3606ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        startValues.viewValues.get(view) : startValues.idValues.get(id);
3616ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                if (endValues.viewValues.get(view) != null) {
3626ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    end = endValues.viewValues.get(view);
363faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    endCopy.remove(view);
364c46181a963be736186ae29101625a05b5c1f0ba8Chet Haase                } else if (id != View.NO_ID) {
3656ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    end = endValues.idValues.get(id);
366faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    View removeView = null;
367faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    for (View viewToRemove : endCopy.keySet()) {
368faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        if (viewToRemove.getId() == id) {
369faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                            removeView = viewToRemove;
370faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        }
371faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
372faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    if (removeView != null) {
373faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        endCopy.remove(removeView);
374faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
375faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
376faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endIdCopy.remove(id);
377faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                if (isValidTarget(view, id)) {
378faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    startValuesList.add(start);
379faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    endValuesList.add(end);
380faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
381faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
382faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                ListView parent = (ListView) view.getParent();
383faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                if (parent.getAdapter().hasStableIds()) {
384faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    int position = parent.getPositionForView(view);
385faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    long itemId = parent.getItemIdAtPosition(position);
3866ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    start = startValues.itemIdValues.get(itemId);
387faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    endItemIdCopy.remove(itemId);
388faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    // TODO: deal with targetIDs for itemIDs for ListView items
389faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    startValuesList.add(start);
390faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    endValuesList.add(end);
391faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
392faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
393faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
3946ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        int startItemIdCopySize = startValues.itemIdValues.size();
395faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        for (int i = 0; i < startItemIdCopySize; ++i) {
3966ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            long id = startValues.itemIdValues.keyAt(i);
397faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (isValidTarget(null, id)) {
3986ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues start = startValues.itemIdValues.get(id);
3996ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues end = endValues.itemIdValues.get(id);
400faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endItemIdCopy.remove(id);
401faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                startValuesList.add(start);
402faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endValuesList.add(end);
403faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
404faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
405faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        // Now walk through the remains of the end set
406faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        for (View view : endCopy.keySet()) {
407faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            int id = view.getId();
408faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (isValidTarget(view, id)) {
4096ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues start = startValues.viewValues.get(view) != null ?
4106ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        startValues.viewValues.get(view) : startValues.idValues.get(id);
411faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                TransitionValues end = endCopy.get(view);
412faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endIdCopy.remove(id);
413faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                startValuesList.add(start);
414faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endValuesList.add(end);
415faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
416faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
417faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        int endIdCopySize = endIdCopy.size();
418faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        for (int i = 0; i < endIdCopySize; ++i) {
419faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            int id = endIdCopy.keyAt(i);
420faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (isValidTarget(null, id)) {
4216ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues start = startValues.idValues.get(id);
422faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                TransitionValues end = endIdCopy.get(id);
423faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                startValuesList.add(start);
424faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                endValuesList.add(end);
425faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
426faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
427faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        int endItemIdCopySize = endItemIdCopy.size();
428faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        for (int i = 0; i < endItemIdCopySize; ++i) {
429faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            long id = endItemIdCopy.keyAt(i);
430faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            // TODO: Deal with targetIDs and itemIDs
4316ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValues start = startValues.itemIdValues.get(id);
432faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues end = endItemIdCopy.get(id);
433faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            startValuesList.add(start);
434faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            endValuesList.add(end);
435faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
436199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
437faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        for (int i = 0; i < startValuesList.size(); ++i) {
438faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues start = startValuesList.get(i);
439faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues end = endValuesList.get(i);
440c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            // Only bother trying to animate with values that differ between start/end
441c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            if (start != null || end != null) {
442c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                if (start == null || !start.equals(end)) {
443c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (DBG) {
444c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        View view = (end != null) ? end.view : start.view;
445c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        Log.d(LOG_TAG, "  differing start/end values for view " +
446c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                view);
447c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        if (start == null || end == null) {
448ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                            Log.d(LOG_TAG, "    " + ((start == null) ?
449ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                                    "start null, end non-null" : "start non-null, end null"));
450c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        } else {
451c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                            for (String key : start.values.keySet()) {
452c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                Object startValue = start.values.get(key);
453c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                Object endValue = end.values.get(key);
454c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                if (startValue != endValue && !startValue.equals(endValue)) {
455c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                    Log.d(LOG_TAG, "    " + key + ": start(" + startValue +
456c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                            "), end(" + endValue +")");
457c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                                }
458c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                            }
459c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        }
460c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
461c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    // TODO: what to do about targetIds and itemIds?
462d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    Animator animator = createAnimator(sceneRoot, start, end);
463c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (animator != null) {
464199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        // Save animation info for future cancellation purposes
465199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        View view = null;
466199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        TransitionValues infoValues = null;
467199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        if (end != null) {
468199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            view = end.view;
469199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            String[] properties = getTransitionProperties();
470199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            if (view != null && properties != null && properties.length > 0) {
471199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                infoValues = new TransitionValues();
472199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                infoValues.view = view;
473199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                TransitionValues newValues = endValues.viewValues.get(view);
474199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                if (newValues != null) {
475199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    for (int j = 0; j < properties.length; ++j) {
476199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                        infoValues.values.put(properties[j],
477199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                                newValues.values.get(properties[j]));
478199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    }
479199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                }
480199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                int numExistingAnims = runningAnimators.size();
481199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                for (int j = 0; j < numExistingAnims; ++j) {
482199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    Animator anim = runningAnimators.keyAt(j);
483199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    AnimationInfo info = runningAnimators.get(anim);
484199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    if (info.values != null && info.view == view &&
485199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                            ((info.name == null && getName() == null) ||
486199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                            info.name.equals(getName()))) {
487199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                        if (info.values.equals(infoValues)) {
488199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                            // Favor the old animator
489199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                            animator = null;
490199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                            break;
491199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                        }
492199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    }
493199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                }
494199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
495199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        } else {
496199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            view = (start != null) ? start.view : null;
497199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
498199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        if (animator != null) {
499199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            AnimationInfo info = new AnimationInfo(view, getName(), infoValues);
500199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            runningAnimators.put(animator, info);
501199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            mAnimators.add(animator);
502199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
503c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
504c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                }
505faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
506faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
507faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
508faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
509faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
510faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Internal utility method for checking whether a given view/id
511faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * is valid for this transition, where "valid" means that either
512faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition has no target/targetId list (the default, in which
513faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * cause the transition should act on all views in the hiearchy), or
514faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the given view is in the target list or the view id is in the
515faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * targetId list. If the target parameter is null, then the target list
516faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * is not checked (this is in the case of ListView items, where the
517faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * views are ignored and only the ids are used).
518faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
519faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    boolean isValidTarget(View target, long targetId) {
520ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetIdExcludes != null && mTargetIdExcludes.contains(targetId)) {
521ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return false;
522ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
523ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetExcludes != null && mTargetExcludes.contains(target)) {
524ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return false;
525ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
526ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetTypeExcludes != null && target != null) {
527ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            int numTypes = mTargetTypeExcludes.size();
528ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            for (int i = 0; i < numTypes; ++i) {
529ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                Class type = mTargetTypeExcludes.get(i);
530ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (type.isInstance(target)) {
531ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    return false;
532ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
533ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
534ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
535d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (mTargetIds.size() == 0 && mTargets.size() == 0) {
536faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            return true;
537faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
538d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (mTargetIds.size() > 0) {
539d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            for (int i = 0; i < mTargetIds.size(); ++i) {
540d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                if (mTargetIds.get(i) == targetId) {
541faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    return true;
542faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
543faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
544faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
545d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (target != null && mTargets.size() > 0) {
546d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            for (int i = 0; i < mTargets.size(); ++i) {
547d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                if (mTargets.get(i) == target) {
548faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    return true;
549faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
550faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
551faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
552faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return false;
553faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
554faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
5550a778eda690a66173733a63622886e888d405c45George Mount    /** @hide */
5560a778eda690a66173733a63622886e888d405c45George Mount    public static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
557199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = sRunningAnimators.get();
558199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (runningAnimators == null) {
559199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            runningAnimators = new ArrayMap<Animator, AnimationInfo>();
560199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            sRunningAnimators.set(runningAnimators);
561199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
562199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return runningAnimators;
563199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
564199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
565faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
5662ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * This is called internally once all animations have been set up by the
5672ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * transition hierarchy. \
568faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
569faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
570faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
571d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    protected void runAnimators() {
572199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (DBG) {
573d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            Log.d(LOG_TAG, "runAnimators() on " + this);
574199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
575199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        start();
576199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
577d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        // Now start every Animator that was previously created for this transition
578199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        for (Animator anim : mAnimators) {
579c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            if (DBG) {
580c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                Log.d(LOG_TAG, "  anim: " + anim);
581c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            }
582199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            if (runningAnimators.containsKey(anim)) {
583199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                start();
584199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                runAnimator(anim, runningAnimators);
585199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
586faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
587199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        mAnimators.clear();
588199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        end();
589faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
590faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
591199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    private void runAnimator(Animator animator,
592199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            final ArrayMap<Animator, AnimationInfo> runningAnimators) {
593e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        if (animator != null) {
594e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            // TODO: could be a single listener instance for all of them since it uses the param
595e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animator.addListener(new AnimatorListenerAdapter() {
596e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                @Override
597e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                public void onAnimationStart(Animator animation) {
598e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                    mCurrentAnimators.add(animation);
599e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                }
600e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                @Override
601e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                public void onAnimationEnd(Animator animation) {
602199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    runningAnimators.remove(animation);
603e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                    mCurrentAnimators.remove(animation);
604e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                }
605e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            });
606e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animate(animator);
607e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        }
608e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    }
609e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase
610faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
611d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Captures the values in the start scene for the properties that this
612d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition monitors. These values are then passed as the startValues
613d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * structure in a later call to
614d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
615d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The main concern for an implementation is what the
616d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * properties are that the transition cares about and what the values are
617d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * for all of those properties. The start and end values will be compared
618d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * later during the
619d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}
620d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * method to determine what, if any, animations, should be run.
621d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
622d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Subclasses must implement this method. The method should only be called by the
623d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition system; it is not intended to be called from external classes.</p>
624d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
625d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param transitionValues The holder for any values that the Transition
626d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * wishes to store. Values are stored in the <code>values</code> field
627d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * of this TransitionValues object and are keyed from
628d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * a String value. For example, to store a view's rotation value,
629d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * a transition might call
630d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionValues.values.put("appname:transitionname:rotation",
631d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * view.getRotation())</code>. The target view will already be stored in
632d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * the transitionValues structure when this method is called.
633d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
634d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #captureEndValues(TransitionValues)
635d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
636d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
637d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public abstract void captureStartValues(TransitionValues transitionValues);
638d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
639d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
640d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Captures the values in the end scene for the properties that this
641d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition monitors. These values are then passed as the endValues
642d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * structure in a later call to
643d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
644d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The main concern for an implementation is what the
645faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * properties are that the transition cares about and what the values are
646faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * for all of those properties. The start and end values will be compared
6472ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * later during the
648d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}
6492ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * method to determine what, if any, animations, should be run.
650faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
651d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Subclasses must implement this method. The method should only be called by the
652d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition system; it is not intended to be called from external classes.</p>
653d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
6542ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * @param transitionValues The holder for any values that the Transition
6552ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * wishes to store. Values are stored in the <code>values</code> field
6562ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * of this TransitionValues object and are keyed from
6572ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * a String value. For example, to store a view's rotation value,
6582ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * a transition might call
6592ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * <code>transitionValues.values.put("appname:transitionname:rotation",
6602ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * view.getRotation())</code>. The target view will already be stored in
6612ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * the transitionValues structure when this method is called.
662d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
663d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #captureStartValues(TransitionValues)
664d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
665faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
666d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public abstract void captureEndValues(TransitionValues transitionValues);
667faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
668faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
669d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Adds the id of a target view that this Transition is interested in
670faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * animating. By default, there are no targetIds, and a Transition will
671faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listen for changes on every view in the hierarchy below the sceneRoot
672d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * of the Scene being transitioned into. Setting targetIds constrains
673faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition to only listen for, and act on, views with these IDs.
674faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Views with different IDs, or no IDs whatsoever, will be ignored.
675faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
676d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Note that using ids to specify targets implies that ids should be unique
677d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * within the view hierarchy underneat the scene root.</p>
678d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
679faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @see View#getId()
680d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param targetId The id of a target view, must be a positive number.
681d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition to which the targetId is added.
682d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Returning the same object makes it easier to chain calls during
683d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * construction, such as
684ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <code>transitionSet.addTransitions(new Fade()).addTarget(someId);</code>
685d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
686ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition addTarget(int targetId) {
687d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (targetId > 0) {
688d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargetIds.add(targetId);
689d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
690d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
691d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
692d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
693d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
694d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Removes the given targetId from the list of ids that this Transition
695d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * is interested in animating.
696d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
697d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param targetId The id of a target view, must be a positive number.
698d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition from which the targetId is removed.
699faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returning the same object makes it easier to chain calls during
700faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * construction, such as
701d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).removeTargetId(someId);</code>
702faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
703ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition removeTarget(int targetId) {
704d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (targetId > 0) {
705d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargetIds.remove(targetId);
706d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
707faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return this;
708faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
709faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
710faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
711ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given id to the list of target ids to exclude from this
712ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
713ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should be added to or removed from the excluded list.
714ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
715ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
716ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
717ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
718ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
719ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
720ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
721ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
722ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
723ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
724ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
725ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
726ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param targetId The id of a target to ignore when running this transition.
727ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
728ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
729ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
730ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
731ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(int targetId, boolean exclude) {
732ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetIdExcludes = excludeId(mTargetIdExcludes, targetId, exclude);
733ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
734ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
735ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
736ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
737ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the children of the given id to the list of targets to exclude
738ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * from this transition. The <code>exclude</code> parameter specifies whether
739ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the children of the target should be added to or removed from the excluded list.
740ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Excluding children in this way provides a simple mechanism for excluding all
741ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * children of specific targets, rather than individually excluding each
742ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * child individually.
743ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
744ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
745ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
746ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
747ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
748ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
749ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
750ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
751ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
752ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
753ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
754ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
755ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param targetId The id of a target whose children should be ignored when running
756ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * this transition.
757ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
758ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded-child targets.
759ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
760ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
761ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(int targetId, boolean exclude) {
762ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetIdChildExcludes = excludeId(mTargetIdChildExcludes, targetId, exclude);
763ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
764ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
765ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
766ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
767ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility method to manage the boilerplate code that is the same whether we
768ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * are excluding targets or their children.
769ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
770ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    private ArrayList<Integer> excludeId(ArrayList<Integer> list, int targetId, boolean exclude) {
771ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (targetId > 0) {
772ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (exclude) {
773ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.add(list, targetId);
774ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            } else {
775ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.remove(list, targetId);
776ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
777ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
778ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return list;
779ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
780ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
781ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
782ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given target to the list of targets to exclude from this
783ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
784ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should be added to or removed from the excluded list.
785ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
786ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
787ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
788ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
789ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
790ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
791ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
792ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
793ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
794ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
795ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
796ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
797ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param target The target to ignore when running this transition.
798ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
799ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
800ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
801ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
802ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(View target, boolean exclude) {
803ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetExcludes = excludeView(mTargetExcludes, target, exclude);
804ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
805ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
806ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
807ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
808ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the children of given target to the list of target children
809ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * to exclude from this transition. The <code>exclude</code> parameter specifies
810ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * whether the target should be added to or removed from the excluded list.
811ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
812ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
813ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
814ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
815ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
816ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
817ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
818ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
819ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
820ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
821ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
822ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
823ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param target The target to ignore when running this transition.
824ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
825ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
826ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
827ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
828ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(View target, boolean exclude) {
829ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetChildExcludes = excludeView(mTargetChildExcludes, target, exclude);
830ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
831ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
832ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
833ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
834ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility method to manage the boilerplate code that is the same whether we
835ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * are excluding targets or their children.
836ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
837ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    private ArrayList<View> excludeView(ArrayList<View> list, View target, boolean exclude) {
838ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (target != null) {
839ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (exclude) {
840ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.add(list, target);
841ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            } else {
842ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.remove(list, target);
843ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
844ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
845ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return list;
846ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
847ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
848ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
849ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given type to the list of types to exclude from this
850ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
851ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * type should be added to or removed from the excluded list.
852ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
853ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
854ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
855ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
856ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
857ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
858ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
859ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
860ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
861ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
862ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
863ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
864ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param type The type to ignore when running this transition.
865ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target type to or remove it from the
866ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded target types.
867ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
868ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
869ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(Class type, boolean exclude) {
870ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetTypeExcludes = excludeType(mTargetTypeExcludes, type, exclude);
871ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
872ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
873ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
874ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
875ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given type to the list of types whose children should
876ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * be excluded from this transition. The <code>exclude</code> parameter
877ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * specifies whether the target type should be added to or removed from
878ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the excluded list.
879ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
880ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
881ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
882ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
883ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
884ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
885ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
886ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
887ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
888ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
889ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
890ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
891ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param type The type to ignore when running this transition.
892ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target type to or remove it from the
893ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded target types.
894ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
895ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
896ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(Class type, boolean exclude) {
897ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        mTargetTypeChildExcludes = excludeType(mTargetTypeChildExcludes, type, exclude);
898ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
899ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
900ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
901ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
902ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility method to manage the boilerplate code that is the same whether we
903ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * are excluding targets or their children.
904ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
905ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    private ArrayList<Class> excludeType(ArrayList<Class> list, Class type, boolean exclude) {
906ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (type != null) {
907ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (exclude) {
908ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.add(list, type);
909ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            } else {
910ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.remove(list, type);
911ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
912ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
913ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return list;
914ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
915ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
916ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
917faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the target view instances that this Transition is interested in
918faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * animating. By default, there are no targets, and a Transition will
919faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listen for changes on every view in the hierarchy below the sceneRoot
920faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * of the Scene being transitioned into. Setting targets constrains
921faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition to only listen for, and act on, these views.
922faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * All other views will be ignored.
923faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
924ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>The target list is like the {@link #addTarget(int) targetId}
925faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * list except this list specifies the actual View instances, not the ids
926faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * of the views. This is an important distinction when scene changes involve
927faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * view hierarchies which have been inflated separately; different views may
928faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * share the same id but not actually be the same instance. If the transition
929ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should treat those views as the same, then {@link #addTarget(int)} should be used
930d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * instead of {@link #addTarget(View)}. If, on the other hand, scene changes involve
931faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * changes all within the same view hierarchy, among views which do not
932d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * necessarily have ids set on them, then the target list of views may be more
933faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * convenient.</p>
934faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
935ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #addTarget(int)
936d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param target A View on which the Transition will act, must be non-null.
937d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition to which the target is added.
938d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Returning the same object makes it easier to chain calls during
939d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * construction, such as
940d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).addTarget(someView);</code>
941d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
942d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition addTarget(View target) {
943d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        mTargets.add(target);
944d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
945d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
946d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
947d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
948d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Removes the given target from the list of targets that this Transition
949d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * is interested in animating.
950d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
951d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param target The target view, must be non-null.
952d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return Transition The Transition from which the target is removed.
953faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returning the same object makes it easier to chain calls during
954faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * construction, such as
955d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).removeTarget(someView);</code>
956faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
957d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition removeTarget(View target) {
958d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (target != null) {
959d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargets.remove(target);
960d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
961faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return this;
962faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
963faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
964faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
965faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returns the array of target IDs that this transition limits itself to
966faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * tracking and animating. If the array is null for both this method and
967faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * {@link #getTargets()}, then this transition is
968faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * not limited to specific views, and will handle changes to any views
969faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * in the hierarchy of a scene change.
970faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
971faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @return the list of target IDs
972faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
973d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public List<Integer> getTargetIds() {
974faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mTargetIds;
975faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
976faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
977faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
978faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returns the array of target views that this transition limits itself to
979faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * tracking and animating. If the array is null for both this method and
980faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * {@link #getTargetIds()}, then this transition is
981faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * not limited to specific views, and will handle changes to any views
982faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * in the hierarchy of a scene change.
983faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
984faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @return the list of target views
985faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
986d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public List<View> getTargets() {
987faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mTargets;
988faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
989faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
990faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
991faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Recursive method that captures values for the given view and the
992faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * hierarchy underneath it.
993faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param sceneRoot The root of the view hierarchy being captured
994faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param start true if this capture is happening before the scene change,
995faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * false otherwise
996faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
997faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    void captureValues(ViewGroup sceneRoot, boolean start) {
998df32aa87150768795816852c6393306893467ecaChet Haase        clearValues(start);
999d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (mTargetIds.size() > 0 || mTargets.size() > 0) {
1000d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargetIds.size() > 0) {
1001d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargetIds.size(); ++i) {
1002d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    int id = mTargetIds.get(i);
1003faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    View view = sceneRoot.findViewById(id);
1004faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    if (view != null) {
1005faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        TransitionValues values = new TransitionValues();
1006faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        values.view = view;
1007d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        if (start) {
1008d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                            captureStartValues(values);
1009d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        } else {
1010d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                            captureEndValues(values);
1011d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        }
1012faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        if (start) {
10136ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                            mStartValues.viewValues.put(view, values);
1014867a86613d4152a93423300f83597300e6ebeebeChet Haase                            if (id >= 0) {
10156ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                                mStartValues.idValues.put(id, values);
1016867a86613d4152a93423300f83597300e6ebeebeChet Haase                            }
1017faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        } else {
10186ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                            mEndValues.viewValues.put(view, values);
1019867a86613d4152a93423300f83597300e6ebeebeChet Haase                            if (id >= 0) {
10206ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                                mEndValues.idValues.put(id, values);
1021867a86613d4152a93423300f83597300e6ebeebeChet Haase                            }
1022faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        }
1023faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
1024faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1025faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1026d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargets.size() > 0) {
1027d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargets.size(); ++i) {
1028d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    View view = mTargets.get(i);
1029faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    if (view != null) {
1030faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        TransitionValues values = new TransitionValues();
1031faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        values.view = view;
1032d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        if (start) {
1033d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                            captureStartValues(values);
1034d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        } else {
1035d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                            captureEndValues(values);
1036d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                        }
1037faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        if (start) {
10386ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                            mStartValues.viewValues.put(view, values);
1039faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        } else {
10406ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                            mEndValues.viewValues.put(view, values);
1041faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        }
1042faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
1043faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1044faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1045faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1046faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            captureHierarchy(sceneRoot, start);
1047faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1048faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1049faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1050faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1051df32aa87150768795816852c6393306893467ecaChet Haase     * Clear valuesMaps for specified start/end state
1052df32aa87150768795816852c6393306893467ecaChet Haase     *
1053df32aa87150768795816852c6393306893467ecaChet Haase     * @param start true if the start values should be cleared, false otherwise
1054df32aa87150768795816852c6393306893467ecaChet Haase     */
1055df32aa87150768795816852c6393306893467ecaChet Haase    void clearValues(boolean start) {
1056df32aa87150768795816852c6393306893467ecaChet Haase        if (start) {
1057df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.viewValues.clear();
1058df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.idValues.clear();
1059df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.itemIdValues.clear();
1060df32aa87150768795816852c6393306893467ecaChet Haase        } else {
1061df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.viewValues.clear();
1062df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.idValues.clear();
1063df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.itemIdValues.clear();
1064df32aa87150768795816852c6393306893467ecaChet Haase        }
1065df32aa87150768795816852c6393306893467ecaChet Haase    }
1066df32aa87150768795816852c6393306893467ecaChet Haase
1067df32aa87150768795816852c6393306893467ecaChet Haase    /**
1068faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Recursive method which captures values for an entire view hierarchy,
1069faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * starting at some root view. Transitions without targetIDs will use this
1070faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * method to capture values for all possible views.
1071faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1072faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param view The view for which to capture values. Children of this View
1073faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * will also be captured, recursively down to the leaf nodes.
1074faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param start true if values are being captured in the start scene, false
1075faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * otherwise.
1076faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1077faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    private void captureHierarchy(View view, boolean start) {
1078faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (view == null) {
1079faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            return;
1080faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
10810a778eda690a66173733a63622886e888d405c45George Mount        if (!isValidTarget(view, view.getId())) {
10820a778eda690a66173733a63622886e888d405c45George Mount            return;
10830a778eda690a66173733a63622886e888d405c45George Mount        }
1084faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        boolean isListViewItem = false;
1085faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (view.getParent() instanceof ListView) {
1086faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            isListViewItem = true;
1087faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1088faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (isListViewItem && !((ListView) view.getParent()).getAdapter().hasStableIds()) {
1089faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            // ignore listview children unless we can track them with stable IDs
1090faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            return;
1091faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1092ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        int id = View.NO_ID;
1093ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        long itemId = View.NO_ID;
1094faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (!isListViewItem) {
1095faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            id = view.getId();
1096faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1097faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            ListView listview = (ListView) view.getParent();
1098faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            int position = listview.getPositionForView(view);
1099ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            itemId = listview.getItemIdAtPosition(position);
1100faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            view.setHasTransientState(true);
1101faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1102ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetIdExcludes != null && mTargetIdExcludes.contains(id)) {
1103ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return;
1104ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1105ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetExcludes != null && mTargetExcludes.contains(view)) {
1106ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return;
1107ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1108ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetTypeExcludes != null && view != null) {
1109ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            int numTypes = mTargetTypeExcludes.size();
1110ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            for (int i = 0; i < numTypes; ++i) {
1111ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (mTargetTypeExcludes.get(i).isInstance(view)) {
1112ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    return;
1113ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
1114ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1115ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1116faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        TransitionValues values = new TransitionValues();
1117faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        values.view = view;
1118d8d7c38533d20062166e5e7ef89b80ff9dbd8903Chet Haase        if (start) {
1119d8d7c38533d20062166e5e7ef89b80ff9dbd8903Chet Haase            captureStartValues(values);
1120d8d7c38533d20062166e5e7ef89b80ff9dbd8903Chet Haase        } else {
1121d8d7c38533d20062166e5e7ef89b80ff9dbd8903Chet Haase            captureEndValues(values);
1122d8d7c38533d20062166e5e7ef89b80ff9dbd8903Chet Haase        }
1123faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (start) {
1124faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (!isListViewItem) {
11256ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                mStartValues.viewValues.put(view, values);
1126867a86613d4152a93423300f83597300e6ebeebeChet Haase                if (id >= 0) {
11276ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    mStartValues.idValues.put((int) id, values);
1128867a86613d4152a93423300f83597300e6ebeebeChet Haase                }
1129faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
1130ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                mStartValues.itemIdValues.put(itemId, values);
1131faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1132faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1133faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (!isListViewItem) {
11346ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                mEndValues.viewValues.put(view, values);
1135867a86613d4152a93423300f83597300e6ebeebeChet Haase                if (id >= 0) {
11366ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    mEndValues.idValues.put((int) id, values);
1137867a86613d4152a93423300f83597300e6ebeebeChet Haase                }
1138faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
1139ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                mEndValues.itemIdValues.put(itemId, values);
1140faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1141faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1142faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (view instanceof ViewGroup) {
1143ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            // Don't traverse child hierarchy if there are any child-excludes on this view
1144ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (mTargetIdChildExcludes != null && mTargetIdChildExcludes.contains(id)) {
1145ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                return;
1146ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1147ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (mTargetChildExcludes != null && mTargetChildExcludes.contains(view)) {
1148ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                return;
1149ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1150ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (mTargetTypeChildExcludes != null && view != null) {
1151ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                int numTypes = mTargetTypeChildExcludes.size();
1152ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                for (int i = 0; i < numTypes; ++i) {
1153ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    if (mTargetTypeChildExcludes.get(i).isInstance(view)) {
1154ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                        return;
1155ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    }
1156ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
1157ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1158faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            ViewGroup parent = (ViewGroup) view;
1159faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            for (int i = 0; i < parent.getChildCount(); ++i) {
1160faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                captureHierarchy(parent.getChildAt(i), start);
1161faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1162faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1163faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1164faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1165faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
11666ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * This method can be called by transitions to get the TransitionValues for
11676ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * any particular view during the transition-playing process. This might be
11686ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * necessary, for example, to query the before/after state of related views
11696ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * for a given transition.
11706ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     */
1171d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public TransitionValues getTransitionValues(View view, boolean start) {
11726ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        if (mParent != null) {
11736ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            return mParent.getTransitionValues(view, start);
11746ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        }
11756ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        TransitionValuesMaps valuesMaps = start ? mStartValues : mEndValues;
11766ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        TransitionValues values = valuesMaps.viewValues.get(view);
11776ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        if (values == null) {
11786ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            int id = view.getId();
11796ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            if (id >= 0) {
11806ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                values = valuesMaps.idValues.get(id);
11816ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            }
11826ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            if (values == null && view.getParent() instanceof ListView) {
11836ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                ListView listview = (ListView) view.getParent();
11846ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                int position = listview.getPositionForView(view);
11856ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                long itemId = listview.getItemIdAtPosition(position);
11866ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                values = valuesMaps.itemIdValues.get(itemId);
11876ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            }
11886ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            // TODO: Doesn't handle the case where a view was parented to a
11896ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            // ListView (with an itemId), but no longer is
11906ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        }
11916ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        return values;
11926ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
11936ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
11946ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    /**
1195199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Pauses this transition, sending out calls to {@link
1196199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * TransitionListener#onTransitionPause(Transition)} to all listeners
1197199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * and pausing all running animators started by this transition.
1198199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1199199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @hide
1200199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
1201199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public void pause() {
1202a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase        if (!mEnded) {
1203a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1204a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            int numOldAnims = runningAnimators.size();
1205a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            for (int i = numOldAnims - 1; i >= 0; i--) {
1206a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                Animator anim = runningAnimators.keyAt(i);
1207a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                anim.pause();
1208a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            }
1209a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1210a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                ArrayList<TransitionListener> tmpListeners =
1211a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1212a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                int numListeners = tmpListeners.size();
1213a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                for (int i = 0; i < numListeners; ++i) {
1214a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    tmpListeners.get(i).onTransitionPause(this);
1215a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                }
1216199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1217a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mPaused = true;
1218199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1219199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1220199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1221199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1222199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Resumes this transition, sending out calls to {@link
1223199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * TransitionListener#onTransitionPause(Transition)} to all listeners
1224199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * and pausing all running animators started by this transition.
1225199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1226199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @hide
1227199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
1228199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public void resume() {
1229199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (mPaused) {
1230a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            if (!mEnded) {
1231a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1232a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                int numOldAnims = runningAnimators.size();
1233a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                for (int i = numOldAnims - 1; i >= 0; i--) {
1234a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    Animator anim = runningAnimators.keyAt(i);
1235a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    anim.resume();
1236a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                }
1237a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                if (mListeners != null && mListeners.size() > 0) {
1238a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    ArrayList<TransitionListener> tmpListeners =
1239a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                            (ArrayList<TransitionListener>) mListeners.clone();
1240a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    int numListeners = tmpListeners.size();
1241a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    for (int i = 0; i < numListeners; ++i) {
1242a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                        tmpListeners.get(i).onTransitionResume(this);
1243a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    }
1244199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                }
1245199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1246199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            mPaused = false;
1247199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1248199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1249199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1250199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1251faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Called by TransitionManager to play the transition. This calls
1252d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * createAnimators() to set things up and create all of the animations and then
12532ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * runAnimations() to actually start the animations.
1254faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
12556ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    void playTransition(ViewGroup sceneRoot) {
1256199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1257199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        int numOldAnims = runningAnimators.size();
1258199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        for (int i = numOldAnims - 1; i >= 0; i--) {
1259199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            Animator anim = runningAnimators.keyAt(i);
1260199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            if (anim != null) {
1261199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                AnimationInfo oldInfo = runningAnimators.get(anim);
126258ad12208afcf9fdce735dead8449c4db375344dChet Haase                if (oldInfo != null && oldInfo.view != null &&
126358ad12208afcf9fdce735dead8449c4db375344dChet Haase                        oldInfo.view.getContext() == sceneRoot.getContext()) {
1264199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    boolean cancel = false;
1265199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    TransitionValues oldValues = oldInfo.values;
1266199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    View oldView = oldInfo.view;
1267199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    TransitionValues newValues = mEndValues.viewValues != null ?
1268199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            mEndValues.viewValues.get(oldView) : null;
126923c61f6bc57a611d97d333bce0d8fe00ab81af4cChet Haase                    if (newValues == null) {
127023c61f6bc57a611d97d333bce0d8fe00ab81af4cChet Haase                        newValues = mEndValues.idValues.get(oldView.getId());
127123c61f6bc57a611d97d333bce0d8fe00ab81af4cChet Haase                    }
1272af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                    if (oldValues != null) {
1273af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                        // if oldValues null, then transition didn't care to stash values,
1274af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                        // and won't get canceled
127523c61f6bc57a611d97d333bce0d8fe00ab81af4cChet Haase                        if (newValues != null) {
1276af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                            for (String key : oldValues.values.keySet()) {
1277af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                Object oldValue = oldValues.values.get(key);
1278af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                Object newValue = newValues.values.get(key);
1279af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                if (oldValue != null && newValue != null &&
1280af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                        !oldValue.equals(newValue)) {
1281af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                    cancel = true;
1282af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                    if (DBG) {
1283af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                        Log.d(LOG_TAG, "Transition.playTransition: " +
1284af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                                "oldValue != newValue for " + key +
1285af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                                ": old, new = " + oldValue + ", " + newValue);
1286af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                    }
1287af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase                                    break;
1288199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                }
1289199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
1290199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
1291199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    }
1292199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    if (cancel) {
1293199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        if (anim.isRunning() || anim.isStarted()) {
1294199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            if (DBG) {
1295199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                Log.d(LOG_TAG, "Canceling anim " + anim);
1296199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
1297199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            anim.cancel();
1298199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        } else {
1299199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            if (DBG) {
1300199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                Log.d(LOG_TAG, "removing anim from info list: " + anim);
1301199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
1302199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            runningAnimators.remove(anim);
1303199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
1304199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    }
1305199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                }
1306199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1307199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1308199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1309d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        createAnimators(sceneRoot, mStartValues, mEndValues);
1310d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        runAnimators();
1311faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1312faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1313faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1314faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This is a utility method used by subclasses to handle standard parts of
1315faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * setting up and running an Animator: it sets the {@link #getDuration()
1316faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * duration} and the {@link #getStartDelay() startDelay}, starts the
1317199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animation, and, when the animator ends, calls {@link #end()}.
1318faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1319faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param animator The Animator to be run during this transition.
1320faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1321faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1322faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1323faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    protected void animate(Animator animator) {
1324faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        // TODO: maybe pass auto-end as a boolean parameter?
1325faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (animator == null) {
1326199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            end();
1327faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1328faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getDuration() >= 0) {
1329faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                animator.setDuration(getDuration());
1330faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1331faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getStartDelay() >= 0) {
1332faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                animator.setStartDelay(getStartDelay());
1333faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1334faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getInterpolator() != null) {
1335faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                animator.setInterpolator(getInterpolator());
1336faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1337faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            animator.addListener(new AnimatorListenerAdapter() {
1338faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                @Override
1339faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                public void onAnimationEnd(Animator animation) {
1340199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    end();
1341faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    animation.removeListener(this);
1342faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1343faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            });
1344faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            animator.start();
1345faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1346faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1347faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1348faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1349faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method is called automatically by the transition and
1350d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * TransitionSet classes prior to a Transition subclass starting;
1351faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * subclasses should not need to call it directly.
1352faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1353faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1354faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1355199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void start() {
1356faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mNumInstances == 0) {
1357faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1358faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                ArrayList<TransitionListener> tmpListeners =
1359faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1360faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                int numListeners = tmpListeners.size();
1361faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                for (int i = 0; i < numListeners; ++i) {
1362faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    tmpListeners.get(i).onTransitionStart(this);
1363faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1364faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1365a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mEnded = false;
1366faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1367faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mNumInstances++;
1368faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1369faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1370faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1371faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method is called automatically by the Transition and
1372d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * TransitionSet classes when a transition finishes, either because
1373faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * a transition did nothing (returned a null Animator from
1374d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link Transition#createAnimator(ViewGroup, TransitionValues,
1375faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * TransitionValues)}) or because the transition returned a valid
1376199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Animator and end() was called in the onAnimationEnd()
1377faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * callback of the AnimatorListener.
1378faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1379faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1380faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1381199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void end() {
1382faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        --mNumInstances;
1383faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mNumInstances == 0) {
1384faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1385faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                ArrayList<TransitionListener> tmpListeners =
1386faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1387faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                int numListeners = tmpListeners.size();
1388faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                for (int i = 0; i < numListeners; ++i) {
1389faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    tmpListeners.get(i).onTransitionEnd(this);
1390faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1391faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
13926ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            for (int i = 0; i < mStartValues.itemIdValues.size(); ++i) {
13936ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues tv = mStartValues.itemIdValues.valueAt(i);
1394faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                View v = tv.view;
1395faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                if (v.hasTransientState()) {
1396faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    v.setHasTransientState(false);
1397faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1398faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
13996ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            for (int i = 0; i < mEndValues.itemIdValues.size(); ++i) {
14006ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                TransitionValues tv = mEndValues.itemIdValues.valueAt(i);
1401faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                View v = tv.view;
1402faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                if (v.hasTransientState()) {
1403faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    v.setHasTransientState(false);
1404faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1405faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1406a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mEnded = true;
1407faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1408faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1409faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1410faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1411faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method cancels a transition that is currently running.
1412d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
1413d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @hide
1414faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1415199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void cancel() {
1416e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        int numAnimators = mCurrentAnimators.size();
141725a738fb257aacfc87d3363a834ed6e0b050c3b1Chet Haase        for (int i = numAnimators - 1; i >= 0; i--) {
1418e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            Animator animator = mCurrentAnimators.get(i);
1419e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animator.cancel();
1420e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        }
1421faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners != null && mListeners.size() > 0) {
1422faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            ArrayList<TransitionListener> tmpListeners =
1423faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    (ArrayList<TransitionListener>) mListeners.clone();
1424faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            int numListeners = tmpListeners.size();
1425faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            for (int i = 0; i < numListeners; ++i) {
1426faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                tmpListeners.get(i).onTransitionCancel(this);
1427faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1428faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1429faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1430faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1431faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1432faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Adds a listener to the set of listeners that are sent events through the
1433faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * life of an animation, such as start, repeat, and end.
1434faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1435faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param listener the listener to be added to the current set of listeners
1436faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * for this animation.
1437d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
1438faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1439d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition addListener(TransitionListener listener) {
1440faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners == null) {
1441faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            mListeners = new ArrayList<TransitionListener>();
1442faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1443faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mListeners.add(listener);
1444d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
1445faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1446faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1447faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1448faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Removes a listener from the set listening to this animation.
1449faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1450faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param listener the listener to be removed from the current set of
1451faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listeners for this transition.
1452d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
1453faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1454d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition removeListener(TransitionListener listener) {
1455faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners == null) {
1456d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            return this;
1457faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1458faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mListeners.remove(listener);
1459faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners.size() == 0) {
1460faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            mListeners = null;
1461faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1462d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
1463faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1464faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1465d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    Transition setSceneRoot(ViewGroup sceneRoot) {
14666ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        mSceneRoot = sceneRoot;
1467d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
14686ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
14696ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
1470b7a7fc9d233bad507ce893882352618b13647058Chet Haase    void setCanRemoveViews(boolean canRemoveViews) {
1471b7a7fc9d233bad507ce893882352618b13647058Chet Haase        mCanRemoveViews = canRemoveViews;
1472b7a7fc9d233bad507ce893882352618b13647058Chet Haase    }
1473b7a7fc9d233bad507ce893882352618b13647058Chet Haase
14740a778eda690a66173733a63622886e888d405c45George Mount    public boolean canRemoveViews() {
14750a778eda690a66173733a63622886e888d405c45George Mount        return mCanRemoveViews;
14760a778eda690a66173733a63622886e888d405c45George Mount    }
14770a778eda690a66173733a63622886e888d405c45George Mount
1478faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    @Override
1479faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public String toString() {
1480faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return toString("");
1481faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1482faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
14836ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    @Override
14846ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    public Transition clone() {
14856ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        Transition clone = null;
14866ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        try {
14876ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            clone = (Transition) super.clone();
1488199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            clone.mAnimators = new ArrayList<Animator>();
14897660d121b2ef21164ed33e6091e5dd50f5d0f939Chet Haase            clone.mStartValues = new TransitionValuesMaps();
14907660d121b2ef21164ed33e6091e5dd50f5d0f939Chet Haase            clone.mEndValues = new TransitionValuesMaps();
14916ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        } catch (CloneNotSupportedException e) {}
14926ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
14936ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        return clone;
14946ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
14956ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
1496199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1497199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the name of this Transition. This name is used internally to distinguish
1498199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * between different transitions to determine when interrupting transitions overlap.
1499d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * For example, a ChangeBounds running on the same target view as another ChangeBounds
1500d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * should determine whether the old transition is animating to different end values
1501d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * and should be canceled in favor of the new transition.
1502199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1503199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * <p>By default, a Transition's name is simply the value of {@link Class#getName()},
1504199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * but subclasses are free to override and return something different.</p>
1505199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1506199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return The name of this transition.
1507199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
1508199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public String getName() {
1509199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return mName;
1510199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1511199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1512faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    String toString(String indent) {
1513faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        String result = indent + getClass().getSimpleName() + "@" +
1514faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                Integer.toHexString(hashCode()) + ": ";
1515c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mDuration != -1) {
1516c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "dur(" + mDuration + ") ";
1517c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
1518c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mStartDelay != -1) {
1519c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "dly(" + mStartDelay + ") ";
1520c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
1521c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mInterpolator != null) {
1522c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "interp(" + mInterpolator + ") ";
1523c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
1524d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (mTargetIds.size() > 0 || mTargets.size() > 0) {
1525c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "tgts(";
1526d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargetIds.size() > 0) {
1527d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargetIds.size(); ++i) {
1528c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (i > 0) {
1529c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        result += ", ";
1530c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
1531d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    result += mTargetIds.get(i);
1532faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1533faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1534d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargets.size() > 0) {
1535d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargets.size(); ++i) {
1536c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (i > 0) {
1537c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        result += ", ";
1538c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
1539d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    result += mTargets.get(i);
1540faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1541faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1542c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += ")";
1543faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1544faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return result;
1545faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1546faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1547faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1548faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * A transition listener receives notifications from a transition.
1549199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Notifications indicate transition lifecycle events.
1550faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1551faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public static interface TransitionListener {
1552faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
1553faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the start of the transition.
1554faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
1555faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The started transition.
1556faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
1557faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionStart(Transition transition);
1558faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1559faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
1560faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the end of the transition. Canceled transitions
1561faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * will always notify listeners of both the cancellation and end
1562199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * events. That is, {@link #onTransitionEnd(Transition)} is always called,
1563faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * regardless of whether the transition was canceled or played
1564faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * through to completion.
1565faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
1566faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The transition which reached its end.
1567faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
1568faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionEnd(Transition transition);
1569faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1570faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
1571faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the cancellation of the transition.
1572d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that cancel may be called by a parent {@link TransitionSet} on
1573199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
1574199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state on target objects which was set at
1575d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
1576d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * createAnimator()} time.
1577faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
1578faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The transition which was canceled.
1579faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
1580faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionCancel(Transition transition);
1581199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1582199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        /**
1583199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * Notification when a transition is paused.
1584d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that createAnimator() may be called by a parent {@link TransitionSet} on
1585199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
1586199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state on target objects which was set at
1587d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
1588d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * createAnimator()} time.
1589199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         *
1590199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * @param transition The transition which was paused.
1591199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         */
1592199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        void onTransitionPause(Transition transition);
1593199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1594199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        /**
1595199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * Notification when a transition is resumed.
1596d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that resume() may be called by a parent {@link TransitionSet} on
1597199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
1598199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state which may have changed in an earlier call
1599199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * to {@link #onTransitionPause(Transition)}.
1600199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         *
1601199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * @param transition The transition which was resumed.
1602199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         */
1603199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        void onTransitionResume(Transition transition);
1604faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1605faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1606faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1607faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Utility adapter class to avoid having to override all three methods
1608faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * whenever someone just wants to listen for a single event.
1609faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1610faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1611faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * */
1612faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public static class TransitionListenerAdapter implements TransitionListener {
1613faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
1614faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionStart(Transition transition) {
1615faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1616faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1617faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
1618faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionEnd(Transition transition) {
1619faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1620faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1621faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
1622faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionCancel(Transition transition) {
1623faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1624199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1625199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        @Override
1626199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        public void onTransitionPause(Transition transition) {
1627199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1628199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1629199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        @Override
1630199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        public void onTransitionResume(Transition transition) {
1631199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1632faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1633faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1634199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1635199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Holds information about each animator used when a new transition starts
1636199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * while other transitions are still running to determine whether a running
1637199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animation should be canceled or a new animation noop'd. The structure holds
1638199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * information about the state that an animation is going to, to be compared to
1639199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * end state of a new animation.
16400a778eda690a66173733a63622886e888d405c45George Mount     * @hide
1641199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
16420a778eda690a66173733a63622886e888d405c45George Mount    public static class AnimationInfo {
16430a778eda690a66173733a63622886e888d405c45George Mount        public View view;
1644199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        String name;
1645199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        TransitionValues values;
1646199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1647199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        AnimationInfo(View view, String name, TransitionValues values) {
1648199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.view = view;
1649199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.name = name;
1650199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.values = values;
1651199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1652199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1653ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1654ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1655ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility class for managing typed ArrayLists efficiently. In particular, this
1656ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * can be useful for lists that we don't expect to be used often (eg, the exclude
1657ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * lists), so we'd like to keep them nulled out by default. This causes the code to
1658ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * become tedious, with constant null checks, code to allocate when necessary,
1659ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * and code to null out the reference when the list is empty. This class encapsulates
1660ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * all of that functionality into simple add()/remove() methods which perform the
1661ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * necessary checks, allocation/null-out as appropriate, and return the
1662ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * resulting list.
1663ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1664ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    private static class ArrayListManager {
1665ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1666ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        /**
1667ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Add the specified item to the list, returning the resulting list.
1668ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * The returned list can either the be same list passed in or, if that
1669ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list was null, the new list that was created.
1670ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         *
1671ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Note that the list holds unique items; if the item already exists in the
1672ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list, the list is not modified.
1673ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         */
1674ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        static <T> ArrayList<T> add(ArrayList<T> list, T item) {
1675ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (list == null) {
1676ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = new ArrayList<T>();
1677ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1678ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (!list.contains(item)) {
1679ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list.add(item);
1680ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1681ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return list;
1682ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1683ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1684ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        /**
1685ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Remove the specified item from the list, returning the resulting list.
1686ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * The returned list can either the be same list passed in or, if that
1687ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list becomes empty as a result of the remove(), the new list was created.
1688ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         */
1689ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        static <T> ArrayList<T> remove(ArrayList<T> list, T item) {
1690ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (list != null) {
1691ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list.remove(item);
1692ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (list.isEmpty()) {
1693ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    list = null;
1694ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
1695ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1696ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return list;
1697ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1698ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1699ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1700faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase}
1701