Transition.java revision 6276cd4b8defba1b6fef47ebc1bbe14498655b94
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;
22ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.content.Context;
23ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.content.res.TypedArray;
24ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.graphics.Path;
25d6107a3170df61d9e776fcd5666acfc9135c6f16George Mountimport android.graphics.Rect;
2608735185f8105710e18ad02297461bec9268e514Chet Haaseimport android.util.ArrayMap;
27ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.util.AttributeSet;
28c43524f3869cc0d36974fce61986017093f2ecd2Chet Haaseimport android.util.Log;
29faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.util.LongSparseArray;
30faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.util.SparseArray;
31d6107a3170df61d9e776fcd5666acfc9135c6f16George Mountimport android.util.SparseLongArray;
32ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.view.InflateException;
33faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.SurfaceView;
34faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.TextureView;
35faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.View;
36faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.ViewGroup;
37faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.ViewOverlay;
38cf68aad3164303df59b2a669d186a94533c9c743George Mountimport android.view.WindowId;
39ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.view.animation.AnimationUtils;
40faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.widget.ListView;
41ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haaseimport android.widget.Spinner;
42faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
43faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport java.util.ArrayList;
44d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haaseimport java.util.List;
45ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport java.util.StringTokenizer;
46ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
47ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport com.android.internal.R;
48faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
49faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/**
50faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * A Transition holds information about animations that will be run on its
51faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * targets during a scene change. Subclasses of this abstract class may
52d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * choreograph several child transitions ({@link TransitionSet} or they may
53faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * perform custom animations themselves. Any Transition has two main jobs:
54faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * (1) capture property values, and (2) play animations based on changes to
55faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * captured property values. A custom transition knows what property values
56faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * on View objects are of interest to it, and also knows how to animate
57faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * changes to those values. For example, the {@link Fade} transition tracks
58faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * changes to visibility-related properties and is able to construct and run
59faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * animations that fade items in or out based on changes to those properties.
60faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase *
61faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * <p>Note: Transitions may not work correctly with either {@link SurfaceView}
62faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * or {@link TextureView}, due to the way that these views are displayed
63faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * on the screen. For SurfaceView, the problem is that the view is updated from
64faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * a non-UI thread, so changes to the view due to transitions (such as moving
65faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * and resizing the view) may be out of sync with the display inside those bounds.
66faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * TextureView is more compatible with transitions in general, but some
67d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * specific transitions (such as {@link Fade}) may not be compatible
68faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * with TextureView because they rely on {@link ViewOverlay} functionality,
69faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * which does not currently work with TextureView.</p>
70d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
71d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * <p>Transitions can be declared in XML resource files inside the <code>res/transition</code>
72d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * directory. Transition resources consist of a tag name for one of the Transition
73d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * subclasses along with attributes to define some of the attributes of that transition.
74d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * For example, here is a minimal resource file that declares a {@link ChangeBounds} transition:
75d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
76d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@sample development/samples/ApiDemos/res/transition/changebounds.xml ChangeBounds}
77d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
78608b87d9e57b71a86374a439bf5c3febd1e142f2George Mount * <p>This TransitionSet contains {@link android.transition.Explode} for visibility,
79608b87d9e57b71a86374a439bf5c3febd1e142f2George Mount * {@link android.transition.ChangeBounds}, {@link android.transition.ChangeTransform},
80990205eada00ad3e575761d19607bb03e12f9aa3George Mount * and {@link android.transition.ChangeClipBounds} and
81990205eada00ad3e575761d19607bb03e12f9aa3George Mount * {@link android.transition.ChangeImageTransform}:</p>
82d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount *
83608b87d9e57b71a86374a439bf5c3febd1e142f2George Mount * {@sample development/samples/ApiDemos/res/transition/explode_move_together.xml MultipleTransform}
84d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount *
8544d663849481576fb649aeb6234086406ced75f1George Mount * <p>Custom transition classes may be instantiated with a <code>transition</code> tag:</p>
8644d663849481576fb649aeb6234086406ced75f1George Mount * <pre>&lt;transition class="my.app.transition.CustomTransition"/></pre>
8744d663849481576fb649aeb6234086406ced75f1George Mount * <p>Custom transition classes loaded from XML must have a public nullary (no argument)
8844d663849481576fb649aeb6234086406ced75f1George Mount * constructor.</p>
8944d663849481576fb649aeb6234086406ced75f1George Mount *
90d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * <p>Note that attributes for the transition are not required, just as they are
91d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * optional when declared in code; Transitions created from XML resources will use
92d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * the same defaults as their code-created equivalents. Here is a slightly more
93d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * elaborate example which declares a {@link TransitionSet} transition with
94d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link ChangeBounds} and {@link Fade} child transitions:</p>
95d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
96d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@sample
97d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * development/samples/ApiDemos/res/transition/changebounds_fadeout_sequential.xml TransitionSet}
98d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
99d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * <p>In this example, the transitionOrdering attribute is used on the TransitionSet
100d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * object to change from the default {@link TransitionSet#ORDERING_TOGETHER} behavior
101d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * to be {@link TransitionSet#ORDERING_SEQUENTIAL} instead. Also, the {@link Fade}
102d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * transition uses a fadingMode of {@link Fade#OUT} instead of the default
103d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * out-in behavior. Finally, note the use of the <code>targets</code> sub-tag, which
104d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * takes a set of {@link android.R.styleable#TransitionTarget target} tags, each
105a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount * of which lists a specific <code>targetId</code>, <code>targetClass</code>,
1060a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount * <code>targetName</code>, <code>excludeId</code>, <code>excludeClass</code>, or
1070a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount * <code>excludeName</code>, which this transition acts upon.
108d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * Use of targets is optional, but can be used to either limit the time spent checking
109d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * attributes on unchanging views, or limiting the types of animations run on specific views.
110d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * In this case, we know that only the <code>grayscaleContainer</code> will be
111d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * disappearing, so we choose to limit the {@link Fade} transition to only that view.</p>
112d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
113d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * Further information on XML resource descriptions for transitions can be found for
114d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link android.R.styleable#Transition}, {@link android.R.styleable#TransitionSet},
115c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu * {@link android.R.styleable#TransitionTarget}, {@link android.R.styleable#Fade},
116c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu * {@link android.R.styleable#Slide}, and {@link android.R.styleable#ChangeTransform}.
117d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase *
118faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */
1196ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haasepublic abstract class Transition implements Cloneable {
120faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
121faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    private static final String LOG_TAG = "Transition";
122faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    static final boolean DBG = false;
123faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1247b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    /**
1257b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * With {@link #setMatchOrder(int...)}, chooses to match by View instance.
1267b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     */
1277b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    public static final int MATCH_INSTANCE = 0x1;
1287b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    private static final int MATCH_FIRST = MATCH_INSTANCE;
1297b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount
1307b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    /**
1317b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * With {@link #setMatchOrder(int...)}, chooses to match by
1320a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * {@link android.view.View#getTransitionName()}. Null names will not be matched.
1337b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     */
1340a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount    public static final int MATCH_NAME = 0x2;
1357b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount
1367b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    /**
1377b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * With {@link #setMatchOrder(int...)}, chooses to match by
1387b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * {@link android.view.View#getId()}. Negative IDs will not be matched.
1397b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     */
1407b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    public static final int MATCH_ID = 0x3;
1417b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount
1427b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    /**
1437b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * With {@link #setMatchOrder(int...)}, chooses to match by the {@link android.widget.Adapter}
1447b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * item id. When {@link android.widget.Adapter#hasStableIds()} returns false, no match
1457b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * will be made for items.
1467b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     */
1477b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    public static final int MATCH_ITEM_ID = 0x4;
1487b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount
1497b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    private static final int MATCH_LAST = MATCH_ITEM_ID;
1507b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount
151ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    private static final String MATCH_INSTANCE_STR = "instance";
152ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    private static final String MATCH_NAME_STR = "name";
153ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    /** To be removed before L release */
154ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    private static final String MATCH_VIEW_NAME_STR = "viewName";
155ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    private static final String MATCH_ID_STR = "id";
156ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    private static final String MATCH_ITEM_ID_STR = "itemId";
157ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
1587b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    private static final int[] DEFAULT_MATCH_ORDER = {
1590a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount        MATCH_NAME,
1607b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        MATCH_INSTANCE,
1617b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        MATCH_ID,
1627b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        MATCH_ITEM_ID,
1637b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    };
1647b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount
165ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    private static final PathMotion STRAIGHT_PATH_MOTION = new PathMotion() {
166ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        @Override
167ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        public Path getPath(float startX, float startY, float endX, float endY) {
168ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            Path path = new Path();
169ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            path.moveTo(startX, startY);
170ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            path.lineTo(endX, endY);
171ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            return path;
172ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        }
173ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    };
174ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
175199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    private String mName = getClass().getName();
176199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
177faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    long mStartDelay = -1;
178faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    long mDuration = -1;
179faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    TimeInterpolator mInterpolator = null;
180d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    ArrayList<Integer> mTargetIds = new ArrayList<Integer>();
181d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    ArrayList<View> mTargets = new ArrayList<View>();
18230da61d477bcb6cc7718f9516c444359352fe148George Mount    ArrayList<String> mTargetNames = null;
18330da61d477bcb6cc7718f9516c444359352fe148George Mount    ArrayList<Class> mTargetTypes = null;
184ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Integer> mTargetIdExcludes = null;
185ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<View> mTargetExcludes = null;
186ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Class> mTargetTypeExcludes = null;
18730da61d477bcb6cc7718f9516c444359352fe148George Mount    ArrayList<String> mTargetNameExcludes = null;
188ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Integer> mTargetIdChildExcludes = null;
189ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<View> mTargetChildExcludes = null;
190ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    ArrayList<Class> mTargetTypeChildExcludes = null;
1916ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    private TransitionValuesMaps mStartValues = new TransitionValuesMaps();
1926ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    private TransitionValuesMaps mEndValues = new TransitionValuesMaps();
193d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    TransitionSet mParent = null;
1947b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    private int[] mMatchOrder = DEFAULT_MATCH_ORDER;
1954d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    ArrayList<TransitionValues> mStartValuesList; // only valid after playTransition starts
1964d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    ArrayList<TransitionValues> mEndValuesList; // only valid after playTransitions starts
1976ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
198199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    // Per-animator information used for later canceling when future transitions overlap
199199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    private static ThreadLocal<ArrayMap<Animator, AnimationInfo>> sRunningAnimators =
200199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            new ThreadLocal<ArrayMap<Animator, AnimationInfo>>();
201199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
202d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    // Scene Root is set at createAnimator() time in the cloned Transition
2036ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    ViewGroup mSceneRoot = null;
2046ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
205b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // Whether removing views from their parent is possible. This is only for views
206b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // in the start scene, which are no longer in the view hierarchy. This property
207b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // is determined by whether the previous Scene was created from a layout
208b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // resource, and thus the views from the exited scene are going away anyway
209b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // and can be removed as necessary to achieve a particular effect, such as
210b7a7fc9d233bad507ce893882352618b13647058Chet Haase    // removing them from parents to add them to overlays.
211b7a7fc9d233bad507ce893882352618b13647058Chet Haase    boolean mCanRemoveViews = false;
212b7a7fc9d233bad507ce893882352618b13647058Chet Haase
213e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    // Track all animators in use in case the transition gets canceled and needs to
214e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    // cancel running animators
215e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    private ArrayList<Animator> mCurrentAnimators = new ArrayList<Animator>();
216e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase
217faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    // Number of per-target instances of this Transition currently running. This count is
218199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    // determined by calls to start() and end()
219faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    int mNumInstances = 0;
220faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
221199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    // Whether this transition is currently paused, due to a call to pause()
222199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    boolean mPaused = false;
223c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase
224a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase    // Whether this transition has ended. Used to avoid pause/resume on transitions
225a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase    // that have completed
226a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase    private boolean mEnded = false;
227a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase
228c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase    // The set of listeners to be sent transition lifecycle events.
229faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    ArrayList<TransitionListener> mListeners = null;
230faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
231d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    // The set of animators collected from calls to createAnimator(),
232d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    // to be run in runAnimators()
233199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    ArrayList<Animator> mAnimators = new ArrayList<Animator>();
234c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase
235d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    // The function for calculating the Animation start delay.
236d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    TransitionPropagation mPropagation;
237d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
238d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    // The rectangular region for Transitions like Explode and TransitionPropagations
239d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    // like CircularPropagation
240d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    EpicenterCallback mEpicenterCallback;
241d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
242d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    // For Fragment shared element transitions, linking views explicitly by mismatching
2430a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount    // transitionNames.
244d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    ArrayMap<String, String> mNameOverrides;
245d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount
246ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    // The function used to interpolate along two-dimensional points. Typically used
247ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    // for adding curves to x/y View motion.
248ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    private PathMotion mPathMotion = STRAIGHT_PATH_MOTION;
249ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
250faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
251faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Constructs a Transition object with no target objects. A transition with
252faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * no targets defaults to running on all target objects in the scene hierarchy
253d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * (if the transition is not contained in a TransitionSet), or all target
254d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * objects passed down from its parent (if it is in a TransitionSet).
255faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
256faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public Transition() {}
257faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
258faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
259ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * Perform inflation from XML and apply a class-specific base style from a
260ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * theme attribute or style resource. This constructor of Transition allows
261ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * subclasses to use their own base style when they are inflating.
262ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *
263ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * @param context The Context the transition is running in, through which it can
264ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *        access the current theme, resources, etc.
265ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * @param attrs The attributes of the XML tag that is inflating the transition.
266ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     */
267ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    public Transition(Context context, AttributeSet attrs) {
268ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
269ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Transition);
270ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        long duration = a.getInt(R.styleable.Transition_duration, -1);
271ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        if (duration >= 0) {
272ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            setDuration(duration);
273ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        }
274ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        long startDelay = a.getInt(R.styleable.Transition_startDelay, -1);
275ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        if (startDelay > 0) {
276ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            setStartDelay(startDelay);
277ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        }
278ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        final int resID = a.getResourceId(com.android.internal.R.styleable.Animator_interpolator, 0);
279ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        if (resID > 0) {
280ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            setInterpolator(AnimationUtils.loadInterpolator(context, resID));
281ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        }
282ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        String matchOrder = a.getString(R.styleable.Transition_matchOrder);
283ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        if (matchOrder != null) {
284ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            setMatchOrder(parseMatchOrder(matchOrder));
285ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        }
286ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        a.recycle();
287ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    }
288ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
289ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    private static int[] parseMatchOrder(String matchOrderString) {
290ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        StringTokenizer st = new StringTokenizer(matchOrderString, ",");
291ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        int matches[] = new int[st.countTokens()];
292ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        int index = 0;
293ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        while (st.hasMoreTokens()) {
294ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            String token = st.nextToken().trim();
295ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            if (MATCH_ID_STR.equalsIgnoreCase(token)) {
296ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount                matches[index] = Transition.MATCH_ID;
297ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            } else if (MATCH_INSTANCE_STR.equalsIgnoreCase(token)) {
298ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount                matches[index] = Transition.MATCH_INSTANCE;
299ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            } else if (MATCH_NAME_STR.equalsIgnoreCase(token)) {
300ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount                matches[index] = Transition.MATCH_NAME;
301ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            } else if (MATCH_VIEW_NAME_STR.equalsIgnoreCase(token)) {
302ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount                matches[index] = Transition.MATCH_NAME;
303ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            } else if (MATCH_ITEM_ID_STR.equalsIgnoreCase(token)) {
304ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount                matches[index] = Transition.MATCH_ITEM_ID;
305ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            } else if (token.isEmpty()) {
306ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount                int[] smallerMatches = new int[matches.length - 1];
307ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount                System.arraycopy(matches, 0, smallerMatches, 0, index);
308ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount                matches = smallerMatches;
309ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount                index--;
310ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            } else {
311ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount                throw new InflateException("Unknown match type in matchOrder: '" + token + "'");
312ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            }
313ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            index++;
314ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        }
315ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        return matches;
316ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    }
317ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
318ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    /**
319faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the duration of this transition. By default, there is no duration
320faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * (indicated by a negative number), which means that the Animator created by
321faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the transition will have its own specified duration. If the duration of a
322faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Transition is set, that duration will override the Animator duration.
323faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
324faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param duration The length of the animation, in milliseconds.
325faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @return This transition object.
326d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @attr ref android.R.styleable#Transition_duration
327faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
328faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public Transition setDuration(long duration) {
329faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mDuration = duration;
330faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return this;
331faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
332faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
333199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
334199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the duration set on this transition. If no duration has been set,
335199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the returned value will be negative, indicating that resulting animators will
336199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * retain their own durations.
337199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
338d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The duration set on this transition, in milliseconds, if one has been
339d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * set, otherwise returns a negative number.
340199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
341faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public long getDuration() {
342faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mDuration;
343faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
344faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
345faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
346faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the startDelay of this transition. By default, there is no delay
347faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * (indicated by a negative number), which means that the Animator created by
348faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the transition will have its own specified startDelay. If the delay of a
349faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Transition is set, that delay will override the Animator delay.
350faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
351faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param startDelay The length of the delay, in milliseconds.
352d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
353d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @attr ref android.R.styleable#Transition_startDelay
354faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
355d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition setStartDelay(long startDelay) {
356faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mStartDelay = startDelay;
357d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
358faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
359faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
360199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
361199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the startDelay set on this transition. If no startDelay has been set,
362199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the returned value will be negative, indicating that resulting animators will
363199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * retain their own startDelays.
364199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
365d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The startDelay set on this transition, in milliseconds, if one has
366d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * been set, otherwise returns a negative number.
367199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
368faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public long getStartDelay() {
369faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mStartDelay;
370faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
371faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
372faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
373faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the interpolator of this transition. By default, the interpolator
374faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * is null, which means that the Animator created by the transition
375faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * will have its own specified interpolator. If the interpolator of a
376faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Transition is set, that interpolator will override the Animator interpolator.
377faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
378faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param interpolator The time interpolator used by the transition
379d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
380d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @attr ref android.R.styleable#Transition_interpolator
381faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
382d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition setInterpolator(TimeInterpolator interpolator) {
383faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mInterpolator = interpolator;
384d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
385faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
386faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
387199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
388199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the interpolator set on this transition. If no interpolator has been set,
389199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the returned value will be null, indicating that resulting animators will
390199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * retain their own interpolators.
391199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
392199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return The interpolator set on this transition, if one has been set, otherwise
393199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * returns null.
394199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
395faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public TimeInterpolator getInterpolator() {
396faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mInterpolator;
397faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
398faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
399faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
400199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the set of property names used stored in the {@link TransitionValues}
401d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * object passed into {@link #captureStartValues(TransitionValues)} that
402199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * this transition cares about for the purposes of canceling overlapping animations.
403199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * When any transition is started on a given scene root, all transitions
404199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * currently running on that same scene root are checked to see whether the
405199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * properties on which they based their animations agree with the end values of
406199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * the same properties in the new transition. If the end values are not equal,
407199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * then the old animation is canceled since the new transition will start a new
408199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animation to these new values. If the values are equal, the old animation is
409199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * allowed to continue and no new animation is started for that transition.
410199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
411199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * <p>A transition does not need to override this method. However, not doing so
412199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * will mean that the cancellation logic outlined in the previous paragraph
413199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * will be skipped for that transition, possibly leading to artifacts as
414199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * old transitions and new transitions on the same targets run in parallel,
415199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animating views toward potentially different end values.</p>
416199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
417199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return An array of property names as described in the class documentation for
418199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * {@link TransitionValues}. The default implementation returns <code>null</code>.
419199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
420199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public String[] getTransitionProperties() {
421199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return null;
422199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
423199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
424199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
425d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * This method creates an animation that will be run for this transition
426d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * given the information in the startValues and endValues structures captured
427d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * earlier for the start and end scenes. Subclasses of Transition should override
428d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * this method. The method should only be called by the transition system; it is
429d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * not intended to be called from external classes.
430d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
431d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>This method is called by the transition's parent (all the way up to the
432faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * topmost Transition in the hierarchy) with the sceneRoot and start/end
4332ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * values that the transition may need to set up initial target values
4342ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * and construct an appropriate animation. For example, if an overall
435d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Transition is a {@link TransitionSet} consisting of several
436faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * child transitions in sequence, then some of the child transitions may
437faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * want to set initial values on target views prior to the overall
4382ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * Transition commencing, to put them in an appropriate state for the
439faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * delay between that start and the child Transition start time. For
440faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * example, a transition that fades an item in may wish to set the starting
441faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * alpha value to 0, to avoid it blinking in prior to the transition
442faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * actually starting the animation. This is necessary because the scene
443faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * change that triggers the Transition will automatically set the end-scene
444faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * on all target views, so a Transition that wants to animate from a
445d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * different value should set that value prior to returning from this method.</p>
446faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
447faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * <p>Additionally, a Transition can perform logic to determine whether
448faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the transition needs to run on the given target and start/end values.
449faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * For example, a transition that resizes objects on the screen may wish
450faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * to avoid running for views which are not present in either the start
451d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * or end scenes.</p>
4522ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     *
4532ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * <p>If there is an animator created and returned from this method, the
4542ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * transition mechanism will apply any applicable duration, startDelay,
4552ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * and interpolator to that animation and start it. A return value of
4562ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * <code>null</code> indicates that no animation should run. The default
4572ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * implementation returns null.</p>
458faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
459faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * <p>The method is called for every applicable target object, which is
460faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * stored in the {@link TransitionValues#view} field.</p>
461faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
462d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
463d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param sceneRoot The root of the transition hierarchy.
464d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param startValues The values for a specific target in the start scene.
465d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param endValues The values for the target in the end scene.
466d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return A Animator to be started at the appropriate time in the
467d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * overall transition for this scene change. A null value means no animation
468d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * should be run.
469faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
470d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
471faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues endValues) {
4722ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase        return null;
473faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
474faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
475faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
4767b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * Sets the order in which Transition matches View start and end values.
4777b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * <p>
4780a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * The default behavior is to match first by {@link android.view.View#getTransitionName()},
4797b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * then by View instance, then by {@link android.view.View#getId()} and finally
4807b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * by its item ID if it is in a direct child of ListView. The caller can
4817b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * choose to have only some or all of the values of {@link #MATCH_INSTANCE},
4820a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * {@link #MATCH_NAME}, {@link #MATCH_ITEM_ID}, and {@link #MATCH_ID}. Only
4837b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * the match algorithms supplied will be used to determine whether Views are the
4847b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * the same in both the start and end Scene. Views that do not match will be considered
4857b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * as entering or leaving the Scene.
4867b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * </p>
4877b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     * @param matches A list of zero or more of {@link #MATCH_INSTANCE},
4880a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     *                {@link #MATCH_NAME}, {@link #MATCH_ITEM_ID}, and {@link #MATCH_ID}.
4897b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     *                If none are provided, then the default match order will be set.
4907b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount     */
4917b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    public void setMatchOrder(int... matches) {
4927b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        if (matches == null || matches.length == 0) {
4937b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount            mMatchOrder = DEFAULT_MATCH_ORDER;
4947b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        } else {
4957b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount            for (int i = 0; i < matches.length; i++) {
4967b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                int match = matches[i];
4977b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                if (!isValidMatch(match)) {
4987b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                    throw new IllegalArgumentException("matches contains invalid value");
4997b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                }
5007b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                if (alreadyContains(matches, i)) {
5017b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                    throw new IllegalArgumentException("matches contains a duplicate value");
5027b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                }
5037b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount            }
5047b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount            mMatchOrder = matches.clone();
5057b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        }
5067b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    }
5077b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount
5087b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    private static boolean isValidMatch(int match) {
5097b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        return (match >= MATCH_FIRST && match <= MATCH_LAST);
5107b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    }
5117b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount
5127b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    private static boolean alreadyContains(int[] array, int searchIndex) {
5137b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        int value = array[searchIndex];
5147b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        for (int i = 0; i < searchIndex; i++) {
5157b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount            if (array[i] == value) {
5167b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                return true;
5177b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount            }
5187b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        }
5197b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        return false;
5207b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    }
5217b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount
5227b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    /**
5234d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * Match start/end values by View instance. Adds matched values to mStartValuesList
5244d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd.
52530da61d477bcb6cc7718f9516c444359352fe148George Mount     */
5264d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    private void matchInstances(ArrayMap<View, TransitionValues> unmatchedStart,
52730da61d477bcb6cc7718f9516c444359352fe148George Mount            ArrayMap<View, TransitionValues> unmatchedEnd) {
52830da61d477bcb6cc7718f9516c444359352fe148George Mount        for (int i = unmatchedStart.size() - 1; i >= 0; i--) {
52930da61d477bcb6cc7718f9516c444359352fe148George Mount            View view = unmatchedStart.keyAt(i);
53030da61d477bcb6cc7718f9516c444359352fe148George Mount            TransitionValues end = unmatchedEnd.remove(view);
53130da61d477bcb6cc7718f9516c444359352fe148George Mount            if (end != null) {
53230da61d477bcb6cc7718f9516c444359352fe148George Mount                TransitionValues start = unmatchedStart.removeAt(i);
5334d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                mStartValuesList.add(start);
5344d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                mEndValuesList.add(end);
53530da61d477bcb6cc7718f9516c444359352fe148George Mount            }
53630da61d477bcb6cc7718f9516c444359352fe148George Mount        }
53730da61d477bcb6cc7718f9516c444359352fe148George Mount    }
53830da61d477bcb6cc7718f9516c444359352fe148George Mount
53930da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
5404d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * Match start/end values by Adapter item ID. Adds matched values to mStartValuesList
5414d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
54230da61d477bcb6cc7718f9516c444359352fe148George Mount     * startItemIds and endItemIds as a guide for which Views have unique item IDs.
54330da61d477bcb6cc7718f9516c444359352fe148George Mount     */
5444d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    private void matchItemIds(ArrayMap<View, TransitionValues> unmatchedStart,
54530da61d477bcb6cc7718f9516c444359352fe148George Mount            ArrayMap<View, TransitionValues> unmatchedEnd,
54630da61d477bcb6cc7718f9516c444359352fe148George Mount            LongSparseArray<View> startItemIds, LongSparseArray<View> endItemIds) {
54730da61d477bcb6cc7718f9516c444359352fe148George Mount        int numStartIds = startItemIds.size();
54830da61d477bcb6cc7718f9516c444359352fe148George Mount        for (int i = 0; i < numStartIds; i++) {
54930da61d477bcb6cc7718f9516c444359352fe148George Mount            View startView = startItemIds.valueAt(i);
55030da61d477bcb6cc7718f9516c444359352fe148George Mount            if (startView != null) {
55130da61d477bcb6cc7718f9516c444359352fe148George Mount                View endView = endItemIds.get(startItemIds.keyAt(i));
55230da61d477bcb6cc7718f9516c444359352fe148George Mount                if (endView != null) {
55330da61d477bcb6cc7718f9516c444359352fe148George Mount                    TransitionValues startValues = unmatchedStart.get(startView);
55430da61d477bcb6cc7718f9516c444359352fe148George Mount                    TransitionValues endValues = unmatchedEnd.get(endView);
55530da61d477bcb6cc7718f9516c444359352fe148George Mount                    if (startValues != null && endValues != null) {
5564d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                        mStartValuesList.add(startValues);
5574d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                        mEndValuesList.add(endValues);
55830da61d477bcb6cc7718f9516c444359352fe148George Mount                        unmatchedStart.remove(startView);
55930da61d477bcb6cc7718f9516c444359352fe148George Mount                        unmatchedEnd.remove(endView);
56030da61d477bcb6cc7718f9516c444359352fe148George Mount                    }
56130da61d477bcb6cc7718f9516c444359352fe148George Mount                }
56230da61d477bcb6cc7718f9516c444359352fe148George Mount            }
56330da61d477bcb6cc7718f9516c444359352fe148George Mount        }
56430da61d477bcb6cc7718f9516c444359352fe148George Mount    }
56530da61d477bcb6cc7718f9516c444359352fe148George Mount
56630da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
5674d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * Match start/end values by Adapter view ID. Adds matched values to mStartValuesList
5684d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
56930da61d477bcb6cc7718f9516c444359352fe148George Mount     * startIds and endIds as a guide for which Views have unique IDs.
57030da61d477bcb6cc7718f9516c444359352fe148George Mount     */
5714d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    private void matchIds(ArrayMap<View, TransitionValues> unmatchedStart,
57230da61d477bcb6cc7718f9516c444359352fe148George Mount            ArrayMap<View, TransitionValues> unmatchedEnd,
57330da61d477bcb6cc7718f9516c444359352fe148George Mount            SparseArray<View> startIds, SparseArray<View> endIds) {
57430da61d477bcb6cc7718f9516c444359352fe148George Mount        int numStartIds = startIds.size();
57530da61d477bcb6cc7718f9516c444359352fe148George Mount        for (int i = 0; i < numStartIds; i++) {
57630da61d477bcb6cc7718f9516c444359352fe148George Mount            View startView = startIds.valueAt(i);
57730da61d477bcb6cc7718f9516c444359352fe148George Mount            if (startView != null && isValidTarget(startView)) {
57830da61d477bcb6cc7718f9516c444359352fe148George Mount                View endView = endIds.get(startIds.keyAt(i));
57930da61d477bcb6cc7718f9516c444359352fe148George Mount                if (endView != null && isValidTarget(endView)) {
58030da61d477bcb6cc7718f9516c444359352fe148George Mount                    TransitionValues startValues = unmatchedStart.get(startView);
58130da61d477bcb6cc7718f9516c444359352fe148George Mount                    TransitionValues endValues = unmatchedEnd.get(endView);
58230da61d477bcb6cc7718f9516c444359352fe148George Mount                    if (startValues != null && endValues != null) {
5834d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                        mStartValuesList.add(startValues);
5844d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                        mEndValuesList.add(endValues);
58530da61d477bcb6cc7718f9516c444359352fe148George Mount                        unmatchedStart.remove(startView);
58630da61d477bcb6cc7718f9516c444359352fe148George Mount                        unmatchedEnd.remove(endView);
58730da61d477bcb6cc7718f9516c444359352fe148George Mount                    }
58830da61d477bcb6cc7718f9516c444359352fe148George Mount                }
58930da61d477bcb6cc7718f9516c444359352fe148George Mount            }
59030da61d477bcb6cc7718f9516c444359352fe148George Mount        }
59130da61d477bcb6cc7718f9516c444359352fe148George Mount    }
59230da61d477bcb6cc7718f9516c444359352fe148George Mount
59330da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
5944d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * Match start/end values by Adapter transitionName. Adds matched values to mStartValuesList
5954d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
5960a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * startNames and endNames as a guide for which Views have unique transitionNames.
59730da61d477bcb6cc7718f9516c444359352fe148George Mount     */
5984d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    private void matchNames(ArrayMap<View, TransitionValues> unmatchedStart,
59930da61d477bcb6cc7718f9516c444359352fe148George Mount            ArrayMap<View, TransitionValues> unmatchedEnd,
60030da61d477bcb6cc7718f9516c444359352fe148George Mount            ArrayMap<String, View> startNames, ArrayMap<String, View> endNames) {
60130da61d477bcb6cc7718f9516c444359352fe148George Mount        int numStartNames = startNames.size();
60230da61d477bcb6cc7718f9516c444359352fe148George Mount        for (int i = 0; i < numStartNames; i++) {
60330da61d477bcb6cc7718f9516c444359352fe148George Mount            View startView = startNames.valueAt(i);
60430da61d477bcb6cc7718f9516c444359352fe148George Mount            if (startView != null && isValidTarget(startView)) {
60530da61d477bcb6cc7718f9516c444359352fe148George Mount                View endView = endNames.get(startNames.keyAt(i));
60630da61d477bcb6cc7718f9516c444359352fe148George Mount                if (endView != null && isValidTarget(endView)) {
60730da61d477bcb6cc7718f9516c444359352fe148George Mount                    TransitionValues startValues = unmatchedStart.get(startView);
60830da61d477bcb6cc7718f9516c444359352fe148George Mount                    TransitionValues endValues = unmatchedEnd.get(endView);
60930da61d477bcb6cc7718f9516c444359352fe148George Mount                    if (startValues != null && endValues != null) {
6104d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                        mStartValuesList.add(startValues);
6114d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                        mEndValuesList.add(endValues);
61230da61d477bcb6cc7718f9516c444359352fe148George Mount                        unmatchedStart.remove(startView);
61330da61d477bcb6cc7718f9516c444359352fe148George Mount                        unmatchedEnd.remove(endView);
61430da61d477bcb6cc7718f9516c444359352fe148George Mount                    }
61530da61d477bcb6cc7718f9516c444359352fe148George Mount                }
61630da61d477bcb6cc7718f9516c444359352fe148George Mount            }
61730da61d477bcb6cc7718f9516c444359352fe148George Mount        }
61830da61d477bcb6cc7718f9516c444359352fe148George Mount    }
61930da61d477bcb6cc7718f9516c444359352fe148George Mount
62030da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
6214d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * Adds all values from unmatchedStart and unmatchedEnd to mStartValuesList and mEndValuesList,
62230da61d477bcb6cc7718f9516c444359352fe148George Mount     * assuming that there is no match between values in the list.
62330da61d477bcb6cc7718f9516c444359352fe148George Mount     */
6244d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    private void addUnmatched(ArrayMap<View, TransitionValues> unmatchedStart,
62530da61d477bcb6cc7718f9516c444359352fe148George Mount            ArrayMap<View, TransitionValues> unmatchedEnd) {
62630da61d477bcb6cc7718f9516c444359352fe148George Mount        // Views that only exist in the start Scene
62730da61d477bcb6cc7718f9516c444359352fe148George Mount        for (int i = 0; i < unmatchedStart.size(); i++) {
6284d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            mStartValuesList.add(unmatchedStart.valueAt(i));
6294d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            mEndValuesList.add(null);
63030da61d477bcb6cc7718f9516c444359352fe148George Mount        }
63130da61d477bcb6cc7718f9516c444359352fe148George Mount
63230da61d477bcb6cc7718f9516c444359352fe148George Mount        // Views that only exist in the end Scene
63330da61d477bcb6cc7718f9516c444359352fe148George Mount        for (int i = 0; i < unmatchedEnd.size(); i++) {
6344d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            mEndValuesList.add(unmatchedEnd.valueAt(i));
6354d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            mStartValuesList.add(null);
63630da61d477bcb6cc7718f9516c444359352fe148George Mount        }
63730da61d477bcb6cc7718f9516c444359352fe148George Mount    }
63830da61d477bcb6cc7718f9516c444359352fe148George Mount
6397b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    private void matchStartAndEnd(TransitionValuesMaps startValues,
6404d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            TransitionValuesMaps endValues) {
6417b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        ArrayMap<View, TransitionValues> unmatchedStart =
6427b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                new ArrayMap<View, TransitionValues>(startValues.viewValues);
6437b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        ArrayMap<View, TransitionValues> unmatchedEnd =
6447b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                new ArrayMap<View, TransitionValues>(endValues.viewValues);
6457b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount
6467b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        for (int i = 0; i < mMatchOrder.length; i++) {
6477b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount            switch (mMatchOrder[i]) {
6487b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                case MATCH_INSTANCE:
6494d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                    matchInstances(unmatchedStart, unmatchedEnd);
6507b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                    break;
6510a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount                case MATCH_NAME:
6524d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                    matchNames(unmatchedStart, unmatchedEnd,
6537b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                            startValues.nameValues, endValues.nameValues);
6547b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                    break;
6557b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                case MATCH_ID:
6564d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                    matchIds(unmatchedStart, unmatchedEnd,
6577b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                            startValues.idValues, endValues.idValues);
6587b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                    break;
6597b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                case MATCH_ITEM_ID:
6604d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                    matchItemIds(unmatchedStart, unmatchedEnd,
6617b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                            startValues.itemIdValues, endValues.itemIdValues);
6627b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount                    break;
6637b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount            }
6647b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount        }
6654d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        addUnmatched(unmatchedStart, unmatchedEnd);
6667b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount    }
6677b75062fb05a9981faf3c0c9f840dbdb9e97e7f7George Mount
66830da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
669d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * This method, essentially a wrapper around all calls to createAnimator for all
670d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * possible target views, is called with the entire set of start/end
671faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * values. The implementation in Transition iterates through these lists
672d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * and calls {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}
673faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * with each set of start/end values on this transition. The
674d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * TransitionSet subclass overrides this method and delegates it to
6752ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * each of its children in succession.
676faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
677faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
678faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
679d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
6804d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
6814d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            ArrayList<TransitionValues> endValuesList) {
682c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (DBG) {
683d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            Log.d(LOG_TAG, "createAnimators() for " + this);
684c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
685199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
686d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        long minStartDelay = Long.MAX_VALUE;
687d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        int minAnimator = mAnimators.size();
688d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        SparseLongArray startDelays = new SparseLongArray();
6894d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        int startValuesListCount = startValuesList.size();
6904d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        for (int i = 0; i < startValuesListCount; ++i) {
691faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues start = startValuesList.get(i);
692faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues end = endValuesList.get(i);
693208dcade9373905b7168feb24db141cd71c45159George Mount            // Only bother trying to animate with valid values that differ between start/end
694208dcade9373905b7168feb24db141cd71c45159George Mount            boolean isInvalidStart = start != null && !isValidTarget(start.view);
695208dcade9373905b7168feb24db141cd71c45159George Mount            boolean isInvalidEnd = end != null && !isValidTarget(end.view);
696208dcade9373905b7168feb24db141cd71c45159George Mount            boolean isChanged = start != end && (start == null || !start.equals(end));
697208dcade9373905b7168feb24db141cd71c45159George Mount            if (isChanged && !isInvalidStart && !isInvalidEnd) {
698208dcade9373905b7168feb24db141cd71c45159George Mount                if (DBG) {
699208dcade9373905b7168feb24db141cd71c45159George Mount                    View view = (end != null) ? end.view : start.view;
700208dcade9373905b7168feb24db141cd71c45159George Mount                    Log.d(LOG_TAG, "  differing start/end values for view " + view);
701208dcade9373905b7168feb24db141cd71c45159George Mount                    if (start == null || end == null) {
702208dcade9373905b7168feb24db141cd71c45159George Mount                        Log.d(LOG_TAG, "    " + ((start == null) ?
703208dcade9373905b7168feb24db141cd71c45159George Mount                                "start null, end non-null" : "start non-null, end null"));
704208dcade9373905b7168feb24db141cd71c45159George Mount                    } else {
705208dcade9373905b7168feb24db141cd71c45159George Mount                        for (String key : start.values.keySet()) {
706208dcade9373905b7168feb24db141cd71c45159George Mount                            Object startValue = start.values.get(key);
707208dcade9373905b7168feb24db141cd71c45159George Mount                            Object endValue = end.values.get(key);
708208dcade9373905b7168feb24db141cd71c45159George Mount                            if (startValue != endValue && !startValue.equals(endValue)) {
709208dcade9373905b7168feb24db141cd71c45159George Mount                                Log.d(LOG_TAG, "    " + key + ": start(" + startValue +
710208dcade9373905b7168feb24db141cd71c45159George Mount                                        "), end(" + endValue + ")");
711c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                            }
712c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        }
713c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
714208dcade9373905b7168feb24db141cd71c45159George Mount                }
715208dcade9373905b7168feb24db141cd71c45159George Mount                // TODO: what to do about targetIds and itemIds?
716208dcade9373905b7168feb24db141cd71c45159George Mount                Animator animator = createAnimator(sceneRoot, start, end);
717208dcade9373905b7168feb24db141cd71c45159George Mount                if (animator != null) {
718208dcade9373905b7168feb24db141cd71c45159George Mount                    // Save animation info for future cancellation purposes
719208dcade9373905b7168feb24db141cd71c45159George Mount                    View view = null;
720208dcade9373905b7168feb24db141cd71c45159George Mount                    TransitionValues infoValues = null;
721208dcade9373905b7168feb24db141cd71c45159George Mount                    if (end != null) {
722208dcade9373905b7168feb24db141cd71c45159George Mount                        view = end.view;
723208dcade9373905b7168feb24db141cd71c45159George Mount                        String[] properties = getTransitionProperties();
724208dcade9373905b7168feb24db141cd71c45159George Mount                        if (view != null && properties != null && properties.length > 0) {
725208dcade9373905b7168feb24db141cd71c45159George Mount                            infoValues = new TransitionValues();
726208dcade9373905b7168feb24db141cd71c45159George Mount                            infoValues.view = view;
727208dcade9373905b7168feb24db141cd71c45159George Mount                            TransitionValues newValues = endValues.viewValues.get(view);
728208dcade9373905b7168feb24db141cd71c45159George Mount                            if (newValues != null) {
729208dcade9373905b7168feb24db141cd71c45159George Mount                                for (int j = 0; j < properties.length; ++j) {
730208dcade9373905b7168feb24db141cd71c45159George Mount                                    infoValues.values.put(properties[j],
731208dcade9373905b7168feb24db141cd71c45159George Mount                                            newValues.values.get(properties[j]));
732199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                }
733208dcade9373905b7168feb24db141cd71c45159George Mount                            }
734208dcade9373905b7168feb24db141cd71c45159George Mount                            int numExistingAnims = runningAnimators.size();
735208dcade9373905b7168feb24db141cd71c45159George Mount                            for (int j = 0; j < numExistingAnims; ++j) {
736208dcade9373905b7168feb24db141cd71c45159George Mount                                Animator anim = runningAnimators.keyAt(j);
737208dcade9373905b7168feb24db141cd71c45159George Mount                                AnimationInfo info = runningAnimators.get(anim);
738208dcade9373905b7168feb24db141cd71c45159George Mount                                if (info.values != null && info.view == view &&
739208dcade9373905b7168feb24db141cd71c45159George Mount                                        ((info.name == null && getName() == null) ||
740208dcade9373905b7168feb24db141cd71c45159George Mount                                                info.name.equals(getName()))) {
741208dcade9373905b7168feb24db141cd71c45159George Mount                                    if (info.values.equals(infoValues)) {
742208dcade9373905b7168feb24db141cd71c45159George Mount                                        // Favor the old animator
743208dcade9373905b7168feb24db141cd71c45159George Mount                                        animator = null;
744208dcade9373905b7168feb24db141cd71c45159George Mount                                        break;
745199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    }
746199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                }
747199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
748199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
749208dcade9373905b7168feb24db141cd71c45159George Mount                    } else {
750208dcade9373905b7168feb24db141cd71c45159George Mount                        view = (start != null) ? start.view : null;
751208dcade9373905b7168feb24db141cd71c45159George Mount                    }
752208dcade9373905b7168feb24db141cd71c45159George Mount                    if (animator != null) {
753208dcade9373905b7168feb24db141cd71c45159George Mount                        if (mPropagation != null) {
754208dcade9373905b7168feb24db141cd71c45159George Mount                            long delay = mPropagation
755208dcade9373905b7168feb24db141cd71c45159George Mount                                    .getStartDelay(sceneRoot, this, start, end);
756208dcade9373905b7168feb24db141cd71c45159George Mount                            startDelays.put(mAnimators.size(), delay);
757208dcade9373905b7168feb24db141cd71c45159George Mount                            minStartDelay = Math.min(delay, minStartDelay);
758199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
7594c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount                        AnimationInfo info = new AnimationInfo(view, getName(), this,
760208dcade9373905b7168feb24db141cd71c45159George Mount                                sceneRoot.getWindowId(), infoValues);
761208dcade9373905b7168feb24db141cd71c45159George Mount                        runningAnimators.put(animator, info);
762208dcade9373905b7168feb24db141cd71c45159George Mount                        mAnimators.add(animator);
763c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
764c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                }
765faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
766faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
767d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (minStartDelay != 0) {
768d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            for (int i = 0; i < startDelays.size(); i++) {
769d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                int index = startDelays.keyAt(i);
770d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                Animator animator = mAnimators.get(index);
771d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                long delay = startDelays.valueAt(i) - minStartDelay + animator.getStartDelay();
772d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                animator.setStartDelay(delay);
773d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
774d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
775faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
776faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
777faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
778faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Internal utility method for checking whether a given view/id
779faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * is valid for this transition, where "valid" means that either
780faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition has no target/targetId list (the default, in which
781faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * cause the transition should act on all views in the hiearchy), or
782faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the given view is in the target list or the view id is in the
783faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * targetId list. If the target parameter is null, then the target list
784faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * is not checked (this is in the case of ListView items, where the
785faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * views are ignored and only the ids are used).
786faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
78730da61d477bcb6cc7718f9516c444359352fe148George Mount    boolean isValidTarget(View target) {
78830da61d477bcb6cc7718f9516c444359352fe148George Mount        int targetId = target.getId();
789ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetIdExcludes != null && mTargetIdExcludes.contains(targetId)) {
790ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return false;
791ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
792ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetExcludes != null && mTargetExcludes.contains(target)) {
793ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return false;
794ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
795ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetTypeExcludes != null && target != null) {
796ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            int numTypes = mTargetTypeExcludes.size();
797ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            for (int i = 0; i < numTypes; ++i) {
798ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                Class type = mTargetTypeExcludes.get(i);
799ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (type.isInstance(target)) {
800ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    return false;
801ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
802ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
803ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
8040a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount        if (mTargetNameExcludes != null && target != null && target.getTransitionName() != null) {
8050a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount            if (mTargetNameExcludes.contains(target.getTransitionName())) {
80630da61d477bcb6cc7718f9516c444359352fe148George Mount                return false;
80730da61d477bcb6cc7718f9516c444359352fe148George Mount            }
80830da61d477bcb6cc7718f9516c444359352fe148George Mount        }
80930da61d477bcb6cc7718f9516c444359352fe148George Mount        if (mTargetIds.size() == 0 && mTargets.size() == 0 &&
81030da61d477bcb6cc7718f9516c444359352fe148George Mount                (mTargetTypes == null || mTargetTypes.isEmpty() &&
81130da61d477bcb6cc7718f9516c444359352fe148George Mount                (mTargetNames == null || mTargetNames.isEmpty()))) {
81230da61d477bcb6cc7718f9516c444359352fe148George Mount            return true;
81330da61d477bcb6cc7718f9516c444359352fe148George Mount        }
81430da61d477bcb6cc7718f9516c444359352fe148George Mount        if (mTargetIds.contains(targetId) || mTargets.contains(target)) {
815faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            return true;
816faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
8170a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount        if (mTargetNames != null && mTargetNames.contains(target.getTransitionName())) {
818a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount            return true;
819faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
820a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount        if (mTargetTypes != null) {
821a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount            for (int i = 0; i < mTargetTypes.size(); ++i) {
822a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount                if (mTargetTypes.get(i).isInstance(target)) {
823faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    return true;
824faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
825faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
826faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
827faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return false;
828faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
829faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
830e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount    private static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
831199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = sRunningAnimators.get();
832199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (runningAnimators == null) {
833199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            runningAnimators = new ArrayMap<Animator, AnimationInfo>();
834199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            sRunningAnimators.set(runningAnimators);
835199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
836199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return runningAnimators;
837199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
838199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
839faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
8402ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * This is called internally once all animations have been set up by the
841d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * transition hierarchy.
842faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
843faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
844faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
845d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    protected void runAnimators() {
846199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (DBG) {
847d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            Log.d(LOG_TAG, "runAnimators() on " + this);
848199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
849199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        start();
850199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
851d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        // Now start every Animator that was previously created for this transition
852199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        for (Animator anim : mAnimators) {
853c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            if (DBG) {
854c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                Log.d(LOG_TAG, "  anim: " + anim);
855c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            }
856199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            if (runningAnimators.containsKey(anim)) {
857199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                start();
858199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                runAnimator(anim, runningAnimators);
859199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
860faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
861199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        mAnimators.clear();
862199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        end();
863faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
864faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
865199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    private void runAnimator(Animator animator,
866199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            final ArrayMap<Animator, AnimationInfo> runningAnimators) {
867e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        if (animator != null) {
868e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            // TODO: could be a single listener instance for all of them since it uses the param
869e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animator.addListener(new AnimatorListenerAdapter() {
870e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                @Override
871e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                public void onAnimationStart(Animator animation) {
872e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                    mCurrentAnimators.add(animation);
873e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                }
874e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                @Override
875e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                public void onAnimationEnd(Animator animation) {
876199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    runningAnimators.remove(animation);
877e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                    mCurrentAnimators.remove(animation);
878e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                }
879e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            });
880e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animate(animator);
881e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        }
882e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    }
883e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase
884faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
885d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Captures the values in the start scene for the properties that this
886d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition monitors. These values are then passed as the startValues
887d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * structure in a later call to
888d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
889d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The main concern for an implementation is what the
890d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * properties are that the transition cares about and what the values are
891d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * for all of those properties. The start and end values will be compared
892d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * later during the
893d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}
894d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * method to determine what, if any, animations, should be run.
895d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
896d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Subclasses must implement this method. The method should only be called by the
897d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition system; it is not intended to be called from external classes.</p>
898d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
899d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param transitionValues The holder for any values that the Transition
900d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * wishes to store. Values are stored in the <code>values</code> field
901d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * of this TransitionValues object and are keyed from
902d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * a String value. For example, to store a view's rotation value,
903d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * a transition might call
904d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionValues.values.put("appname:transitionname:rotation",
905d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * view.getRotation())</code>. The target view will already be stored in
906d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * the transitionValues structure when this method is called.
907d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
908d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #captureEndValues(TransitionValues)
909d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
910d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
911d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public abstract void captureStartValues(TransitionValues transitionValues);
912d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
913d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
914d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Captures the values in the end scene for the properties that this
915d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition monitors. These values are then passed as the endValues
916d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * structure in a later call to
917d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
918d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The main concern for an implementation is what the
919faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * properties are that the transition cares about and what the values are
920faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * for all of those properties. The start and end values will be compared
9212ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * later during the
922d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}
9232ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * method to determine what, if any, animations, should be run.
924faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
925d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Subclasses must implement this method. The method should only be called by the
926d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition system; it is not intended to be called from external classes.</p>
927d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
9282ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * @param transitionValues The holder for any values that the Transition
9292ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * wishes to store. Values are stored in the <code>values</code> field
9302ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * of this TransitionValues object and are keyed from
9312ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * a String value. For example, to store a view's rotation value,
9322ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * a transition might call
9332ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * <code>transitionValues.values.put("appname:transitionname:rotation",
9342ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * view.getRotation())</code>. The target view will already be stored in
9352ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * the transitionValues structure when this method is called.
936d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
937d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #captureStartValues(TransitionValues)
938d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
939faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
940d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public abstract void captureEndValues(TransitionValues transitionValues);
941faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
942faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
943d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Adds the id of a target view that this Transition is interested in
944faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * animating. By default, there are no targetIds, and a Transition will
945faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listen for changes on every view in the hierarchy below the sceneRoot
946d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * of the Scene being transitioned into. Setting targetIds constrains
947faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition to only listen for, and act on, views with these IDs.
948faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Views with different IDs, or no IDs whatsoever, will be ignored.
949faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
950d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Note that using ids to specify targets implies that ids should be unique
951d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * within the view hierarchy underneat the scene root.</p>
952d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
953faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @see View#getId()
954d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param targetId The id of a target view, must be a positive number.
955d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition to which the targetId is added.
956d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Returning the same object makes it easier to chain calls during
957d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * construction, such as
958ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <code>transitionSet.addTransitions(new Fade()).addTarget(someId);</code>
959d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
960ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition addTarget(int targetId) {
961d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (targetId > 0) {
962d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargetIds.add(targetId);
963d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
964d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
965d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
966d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
967d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
9680a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Adds the transitionName of a target view that this Transition is interested in
96930da61d477bcb6cc7718f9516c444359352fe148George Mount     * animating. By default, there are no targetNames, and a Transition will
97030da61d477bcb6cc7718f9516c444359352fe148George Mount     * listen for changes on every view in the hierarchy below the sceneRoot
97130da61d477bcb6cc7718f9516c444359352fe148George Mount     * of the Scene being transitioned into. Setting targetNames constrains
9720a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * the Transition to only listen for, and act on, views with these transitionNames.
9730a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Views with different transitionNames, or no transitionName whatsoever, will be ignored.
97430da61d477bcb6cc7718f9516c444359352fe148George Mount     *
9750a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * <p>Note that transitionNames should be unique within the view hierarchy.</p>
97630da61d477bcb6cc7718f9516c444359352fe148George Mount     *
9770a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @see android.view.View#getTransitionName()
9780a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @param targetName The transitionName of a target view, must be non-null.
9790a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @return The Transition to which the target transitionName is added.
98030da61d477bcb6cc7718f9516c444359352fe148George Mount     * Returning the same object makes it easier to chain calls during
98130da61d477bcb6cc7718f9516c444359352fe148George Mount     * construction, such as
98230da61d477bcb6cc7718f9516c444359352fe148George Mount     * <code>transitionSet.addTransitions(new Fade()).addTarget(someName);</code>
98330da61d477bcb6cc7718f9516c444359352fe148George Mount     */
98430da61d477bcb6cc7718f9516c444359352fe148George Mount    public Transition addTarget(String targetName) {
98530da61d477bcb6cc7718f9516c444359352fe148George Mount        if (targetName != null) {
98658bbdbd1f1e2b2ed2e82caad6de6411fa2380cdcGeorge Mount            if (mTargetNames == null) {
98730da61d477bcb6cc7718f9516c444359352fe148George Mount                mTargetNames = new ArrayList<String>();
98830da61d477bcb6cc7718f9516c444359352fe148George Mount            }
98930da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetNames.add(targetName);
99030da61d477bcb6cc7718f9516c444359352fe148George Mount        }
99130da61d477bcb6cc7718f9516c444359352fe148George Mount        return this;
99230da61d477bcb6cc7718f9516c444359352fe148George Mount    }
99330da61d477bcb6cc7718f9516c444359352fe148George Mount
99430da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
995a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * Adds the Class of a target view that this Transition is interested in
996a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * animating. By default, there are no targetTypes, and a Transition will
997a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * listen for changes on every view in the hierarchy below the sceneRoot
998a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * of the Scene being transitioned into. Setting targetTypes constrains
999a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * the Transition to only listen for, and act on, views with these classes.
1000a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * Views with different classes will be ignored.
1001a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     *
1002a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * <p>Note that any View that can be cast to targetType will be included, so
1003a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * if targetType is <code>View.class</code>, all Views will be included.</p>
1004a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     *
1005a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @see #addTarget(int)
1006a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @see #addTarget(android.view.View)
1007a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @see #excludeTarget(Class, boolean)
1008a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @see #excludeChildren(Class, boolean)
1009a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     *
1010a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @param targetType The type to include when running this transition.
1011a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @return The Transition to which the target class was added.
1012a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * Returning the same object makes it easier to chain calls during
1013a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * construction, such as
1014a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * <code>transitionSet.addTransitions(new Fade()).addTarget(ImageView.class);</code>
1015a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     */
1016a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount    public Transition addTarget(Class targetType) {
101730da61d477bcb6cc7718f9516c444359352fe148George Mount        if (targetType != null) {
101830da61d477bcb6cc7718f9516c444359352fe148George Mount            if (mTargetTypes == null) {
101930da61d477bcb6cc7718f9516c444359352fe148George Mount                mTargetTypes = new ArrayList<Class>();
102030da61d477bcb6cc7718f9516c444359352fe148George Mount            }
102130da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetTypes.add(targetType);
1022a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount        }
1023a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount        return this;
1024a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount    }
1025a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount
1026a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount    /**
1027d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Removes the given targetId from the list of ids that this Transition
1028d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * is interested in animating.
1029d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
1030d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param targetId The id of a target view, must be a positive number.
1031d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition from which the targetId is removed.
1032faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returning the same object makes it easier to chain calls during
1033faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * construction, such as
1034d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).removeTargetId(someId);</code>
1035faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1036ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition removeTarget(int targetId) {
1037d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (targetId > 0) {
1038d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargetIds.remove(targetId);
1039d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
1040faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return this;
1041faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1042faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1043faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
10440a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Removes the given targetName from the list of transitionNames that this Transition
104530da61d477bcb6cc7718f9516c444359352fe148George Mount     * is interested in animating.
104630da61d477bcb6cc7718f9516c444359352fe148George Mount     *
10470a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @param targetName The transitionName of a target view, must not be null.
104830da61d477bcb6cc7718f9516c444359352fe148George Mount     * @return The Transition from which the targetName is removed.
104930da61d477bcb6cc7718f9516c444359352fe148George Mount     * Returning the same object makes it easier to chain calls during
105030da61d477bcb6cc7718f9516c444359352fe148George Mount     * construction, such as
105130da61d477bcb6cc7718f9516c444359352fe148George Mount     * <code>transitionSet.addTransitions(new Fade()).removeTargetName(someName);</code>
105230da61d477bcb6cc7718f9516c444359352fe148George Mount     */
105330da61d477bcb6cc7718f9516c444359352fe148George Mount    public Transition removeTarget(String targetName) {
105430da61d477bcb6cc7718f9516c444359352fe148George Mount        if (targetName != null && mTargetNames != null) {
105530da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetNames.remove(targetName);
105630da61d477bcb6cc7718f9516c444359352fe148George Mount        }
105730da61d477bcb6cc7718f9516c444359352fe148George Mount        return this;
105830da61d477bcb6cc7718f9516c444359352fe148George Mount    }
105930da61d477bcb6cc7718f9516c444359352fe148George Mount
106030da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
1061ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given id to the list of target ids to exclude from this
1062ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
1063ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should be added to or removed from the excluded list.
1064ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1065ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1066ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1067ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1068ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1069ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1070ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1071ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1072ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
1073ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
1074ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
1075ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1076ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param targetId The id of a target to ignore when running this transition.
1077ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
1078ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
1079ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1080ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1081ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(int targetId, boolean exclude) {
108230da61d477bcb6cc7718f9516c444359352fe148George Mount        if (targetId >= 0) {
108330da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetIdExcludes = excludeObject(mTargetIdExcludes, targetId, exclude);
108430da61d477bcb6cc7718f9516c444359352fe148George Mount        }
108530da61d477bcb6cc7718f9516c444359352fe148George Mount        return this;
108630da61d477bcb6cc7718f9516c444359352fe148George Mount    }
108730da61d477bcb6cc7718f9516c444359352fe148George Mount
108830da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
10890a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Whether to add the given transitionName to the list of target transitionNames to exclude
10900a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * from this transition. The <code>exclude</code> parameter specifies whether the target
109130da61d477bcb6cc7718f9516c444359352fe148George Mount     * should be added to or removed from the excluded list.
109230da61d477bcb6cc7718f9516c444359352fe148George Mount     *
109330da61d477bcb6cc7718f9516c444359352fe148George Mount     * <p>Excluding targets is a general mechanism for allowing transitions to run on
109430da61d477bcb6cc7718f9516c444359352fe148George Mount     * a view hierarchy while skipping target views that should not be part of
109530da61d477bcb6cc7718f9516c444359352fe148George Mount     * the transition. For example, you may want to avoid animating children
109630da61d477bcb6cc7718f9516c444359352fe148George Mount     * of a specific ListView or Spinner. Views can be excluded by their
10970a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * id, their instance reference, their transitionName, or by the Class of that view
109830da61d477bcb6cc7718f9516c444359352fe148George Mount     * (eg, {@link Spinner}).</p>
109930da61d477bcb6cc7718f9516c444359352fe148George Mount     *
110030da61d477bcb6cc7718f9516c444359352fe148George Mount     * @see #excludeTarget(View, boolean)
110130da61d477bcb6cc7718f9516c444359352fe148George Mount     * @see #excludeTarget(int, boolean)
110230da61d477bcb6cc7718f9516c444359352fe148George Mount     * @see #excludeTarget(Class, boolean)
110330da61d477bcb6cc7718f9516c444359352fe148George Mount     *
11040a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @param targetName The name of a target to ignore when running this transition.
110530da61d477bcb6cc7718f9516c444359352fe148George Mount     * @param exclude Whether to add the target to or remove the target from the
110630da61d477bcb6cc7718f9516c444359352fe148George Mount     * current list of excluded targets.
110730da61d477bcb6cc7718f9516c444359352fe148George Mount     * @return This transition object.
110830da61d477bcb6cc7718f9516c444359352fe148George Mount     */
11090a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount    public Transition excludeTarget(String targetName, boolean exclude) {
11100a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount        mTargetNameExcludes = excludeObject(mTargetNameExcludes, targetName, exclude);
1111ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
1112ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1113ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1114ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1115ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the children of the given id to the list of targets to exclude
1116ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * from this transition. The <code>exclude</code> parameter specifies whether
1117ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the children of the target should be added to or removed from the excluded list.
1118ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Excluding children in this way provides a simple mechanism for excluding all
1119ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * children of specific targets, rather than individually excluding each
1120ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * child individually.
1121ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1122ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1123ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1124ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1125ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1126ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1127ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1128ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1129ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
1130ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
1131ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
1132ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1133ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param targetId The id of a target whose children should be ignored when running
1134ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * this transition.
1135ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
1136ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded-child targets.
1137ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1138ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1139ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(int targetId, boolean exclude) {
114030da61d477bcb6cc7718f9516c444359352fe148George Mount        if (targetId >= 0) {
114130da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetIdChildExcludes = excludeObject(mTargetIdChildExcludes, targetId, exclude);
1142ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
114330da61d477bcb6cc7718f9516c444359352fe148George Mount        return this;
1144ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1145ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1146ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1147ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given target to the list of targets to exclude from this
1148ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
1149ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should be added to or removed from the excluded list.
1150ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1151ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1152ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1153ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1154ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1155ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1156ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1157ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1158ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
1159ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
1160ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
1161ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1162ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param target The target to ignore when running this transition.
1163ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
1164ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
1165ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1166ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1167ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(View target, boolean exclude) {
116830da61d477bcb6cc7718f9516c444359352fe148George Mount        mTargetExcludes = excludeObject(mTargetExcludes, target, exclude);
1169ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
1170ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1171ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1172ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1173ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the children of given target to the list of target children
1174ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * to exclude from this transition. The <code>exclude</code> parameter specifies
1175ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * whether the target should be added to or removed from the excluded list.
1176ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1177ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1178ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1179ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1180ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1181ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1182ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1183ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1184ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
1185ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
1186ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
1187ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1188ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param target The target to ignore when running this transition.
1189ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
1190ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
1191ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1192ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1193ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(View target, boolean exclude) {
119430da61d477bcb6cc7718f9516c444359352fe148George Mount        mTargetChildExcludes = excludeObject(mTargetChildExcludes, target, exclude);
1195ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
1196ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1197ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1198ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1199ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility method to manage the boilerplate code that is the same whether we
1200ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * are excluding targets or their children.
1201ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
120230da61d477bcb6cc7718f9516c444359352fe148George Mount    private static <T> ArrayList<T> excludeObject(ArrayList<T> list, T target, boolean exclude) {
1203ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (target != null) {
1204ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (exclude) {
1205ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.add(list, target);
1206ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            } else {
1207ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.remove(list, target);
1208ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1209ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1210ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return list;
1211ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1212ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1213ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1214ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given type to the list of types to exclude from this
1215ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
1216ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * type should be added to or removed from the excluded list.
1217ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1218ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1219ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1220ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1221ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1222ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1223ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1224ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1225ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
1226ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
1227ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
1228ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1229ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param type The type to ignore when running this transition.
1230ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target type to or remove it from the
1231ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded target types.
1232ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1233ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1234ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(Class type, boolean exclude) {
123530da61d477bcb6cc7718f9516c444359352fe148George Mount        mTargetTypeExcludes = excludeObject(mTargetTypeExcludes, type, exclude);
1236ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
1237ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1238ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1239ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1240ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given type to the list of types whose children should
1241ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * be excluded from this transition. The <code>exclude</code> parameter
1242ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * specifies whether the target type should be added to or removed from
1243ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the excluded list.
1244ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1245ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1246ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1247ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1248ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1249ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1250ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1251ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1252ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
1253ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
1254ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
1255ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1256ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param type The type to ignore when running this transition.
1257ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target type to or remove it from the
1258ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded target types.
1259ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1260ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1261ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(Class type, boolean exclude) {
126230da61d477bcb6cc7718f9516c444359352fe148George Mount        mTargetTypeChildExcludes = excludeObject(mTargetTypeChildExcludes, type, exclude);
1263ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
1264ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1265ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1266ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1267faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the target view instances that this Transition is interested in
1268faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * animating. By default, there are no targets, and a Transition will
1269faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listen for changes on every view in the hierarchy below the sceneRoot
1270faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * of the Scene being transitioned into. Setting targets constrains
1271faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition to only listen for, and act on, these views.
1272faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * All other views will be ignored.
1273faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1274ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>The target list is like the {@link #addTarget(int) targetId}
1275faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * list except this list specifies the actual View instances, not the ids
1276faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * of the views. This is an important distinction when scene changes involve
1277faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * view hierarchies which have been inflated separately; different views may
1278faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * share the same id but not actually be the same instance. If the transition
1279ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should treat those views as the same, then {@link #addTarget(int)} should be used
1280d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * instead of {@link #addTarget(View)}. If, on the other hand, scene changes involve
1281faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * changes all within the same view hierarchy, among views which do not
1282d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * necessarily have ids set on them, then the target list of views may be more
1283faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * convenient.</p>
1284faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1285ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #addTarget(int)
1286d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param target A View on which the Transition will act, must be non-null.
1287d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition to which the target is added.
1288d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Returning the same object makes it easier to chain calls during
1289d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * construction, such as
1290d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).addTarget(someView);</code>
1291d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
1292d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition addTarget(View target) {
1293d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        mTargets.add(target);
1294d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
1295d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
1296d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
1297d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
1298d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Removes the given target from the list of targets that this Transition
1299d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * is interested in animating.
1300d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
1301d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param target The target view, must be non-null.
1302d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return Transition The Transition from which the target is removed.
1303faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returning the same object makes it easier to chain calls during
1304faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * construction, such as
1305d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).removeTarget(someView);</code>
1306faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1307d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition removeTarget(View target) {
1308d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (target != null) {
1309d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargets.remove(target);
1310d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
1311faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return this;
1312faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1313faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1314faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
131530da61d477bcb6cc7718f9516c444359352fe148George Mount     * Removes the given target from the list of targets that this Transition
131630da61d477bcb6cc7718f9516c444359352fe148George Mount     * is interested in animating.
131730da61d477bcb6cc7718f9516c444359352fe148George Mount     *
131830da61d477bcb6cc7718f9516c444359352fe148George Mount     * @param target The type of the target view, must be non-null.
131930da61d477bcb6cc7718f9516c444359352fe148George Mount     * @return Transition The Transition from which the target is removed.
132030da61d477bcb6cc7718f9516c444359352fe148George Mount     * Returning the same object makes it easier to chain calls during
132130da61d477bcb6cc7718f9516c444359352fe148George Mount     * construction, such as
132230da61d477bcb6cc7718f9516c444359352fe148George Mount     * <code>transitionSet.addTransitions(new Fade()).removeTarget(someType);</code>
132330da61d477bcb6cc7718f9516c444359352fe148George Mount     */
132430da61d477bcb6cc7718f9516c444359352fe148George Mount    public Transition removeTarget(Class target) {
132530da61d477bcb6cc7718f9516c444359352fe148George Mount        if (target != null) {
132630da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetTypes.remove(target);
132730da61d477bcb6cc7718f9516c444359352fe148George Mount        }
132830da61d477bcb6cc7718f9516c444359352fe148George Mount        return this;
132930da61d477bcb6cc7718f9516c444359352fe148George Mount    }
133030da61d477bcb6cc7718f9516c444359352fe148George Mount
133130da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
133230da61d477bcb6cc7718f9516c444359352fe148George Mount     * Returns the list of target IDs that this transition limits itself to
133330da61d477bcb6cc7718f9516c444359352fe148George Mount     * tracking and animating. If the list is null or empty for
13340a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
133530da61d477bcb6cc7718f9516c444359352fe148George Mount     * {@link #getTargetTypes()} then this transition is
1336faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * not limited to specific views, and will handle changes to any views
1337faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * in the hierarchy of a scene change.
1338faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1339faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @return the list of target IDs
1340faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1341d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public List<Integer> getTargetIds() {
1342faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mTargetIds;
1343faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1344faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1345faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
134630da61d477bcb6cc7718f9516c444359352fe148George Mount     * Returns the list of target views that this transition limits itself to
134730da61d477bcb6cc7718f9516c444359352fe148George Mount     * tracking and animating. If the list is null or empty for
13480a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
134930da61d477bcb6cc7718f9516c444359352fe148George Mount     * {@link #getTargetTypes()} then this transition is
1350faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * not limited to specific views, and will handle changes to any views
1351faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * in the hierarchy of a scene change.
1352faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1353faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @return the list of target views
1354faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1355d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public List<View> getTargets() {
1356faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mTargets;
1357faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1358faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1359faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
13600a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Returns the list of target transitionNames that this transition limits itself to
136130da61d477bcb6cc7718f9516c444359352fe148George Mount     * tracking and animating. If the list is null or empty for
13620a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
136330da61d477bcb6cc7718f9516c444359352fe148George Mount     * {@link #getTargetTypes()} then this transition is
136430da61d477bcb6cc7718f9516c444359352fe148George Mount     * not limited to specific views, and will handle changes to any views
136530da61d477bcb6cc7718f9516c444359352fe148George Mount     * in the hierarchy of a scene change.
136630da61d477bcb6cc7718f9516c444359352fe148George Mount     *
13670a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @return the list of target transitionNames
13680a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     */
13690a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount    public List<String> getTargetNames() {
13700a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount        return mTargetNames;
13710a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount    }
13720a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount
13730a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount    /**
13740a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * To be removed before L release.
13750a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @hide
137630da61d477bcb6cc7718f9516c444359352fe148George Mount     */
137730da61d477bcb6cc7718f9516c444359352fe148George Mount    public List<String> getTargetViewNames() {
137830da61d477bcb6cc7718f9516c444359352fe148George Mount        return mTargetNames;
137930da61d477bcb6cc7718f9516c444359352fe148George Mount    }
138030da61d477bcb6cc7718f9516c444359352fe148George Mount
138130da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
13820a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Returns the list of target transitionNames that this transition limits itself to
138330da61d477bcb6cc7718f9516c444359352fe148George Mount     * tracking and animating. If the list is null or empty for
13840a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
138530da61d477bcb6cc7718f9516c444359352fe148George Mount     * {@link #getTargetTypes()} then this transition is
138630da61d477bcb6cc7718f9516c444359352fe148George Mount     * not limited to specific views, and will handle changes to any views
138730da61d477bcb6cc7718f9516c444359352fe148George Mount     * in the hierarchy of a scene change.
138830da61d477bcb6cc7718f9516c444359352fe148George Mount     *
138930da61d477bcb6cc7718f9516c444359352fe148George Mount     * @return the list of target Types
139030da61d477bcb6cc7718f9516c444359352fe148George Mount     */
139130da61d477bcb6cc7718f9516c444359352fe148George Mount    public List<Class> getTargetTypes() {
139230da61d477bcb6cc7718f9516c444359352fe148George Mount        return mTargetTypes;
139330da61d477bcb6cc7718f9516c444359352fe148George Mount    }
139430da61d477bcb6cc7718f9516c444359352fe148George Mount
139530da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
1396faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Recursive method that captures values for the given view and the
1397faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * hierarchy underneath it.
1398faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param sceneRoot The root of the view hierarchy being captured
1399faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param start true if this capture is happening before the scene change,
1400faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * false otherwise
1401faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1402faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    void captureValues(ViewGroup sceneRoot, boolean start) {
1403df32aa87150768795816852c6393306893467ecaChet Haase        clearValues(start);
140430da61d477bcb6cc7718f9516c444359352fe148George Mount        if ((mTargetIds.size() > 0 || mTargets.size() > 0)
140530da61d477bcb6cc7718f9516c444359352fe148George Mount                && (mTargetNames == null || mTargetNames.isEmpty())
140630da61d477bcb6cc7718f9516c444359352fe148George Mount                && (mTargetTypes == null || mTargetTypes.isEmpty())) {
140730da61d477bcb6cc7718f9516c444359352fe148George Mount            for (int i = 0; i < mTargetIds.size(); ++i) {
140830da61d477bcb6cc7718f9516c444359352fe148George Mount                int id = mTargetIds.get(i);
140930da61d477bcb6cc7718f9516c444359352fe148George Mount                View view = sceneRoot.findViewById(id);
141030da61d477bcb6cc7718f9516c444359352fe148George Mount                if (view != null) {
141130da61d477bcb6cc7718f9516c444359352fe148George Mount                    TransitionValues values = new TransitionValues();
141230da61d477bcb6cc7718f9516c444359352fe148George Mount                    values.view = view;
141330da61d477bcb6cc7718f9516c444359352fe148George Mount                    if (start) {
141430da61d477bcb6cc7718f9516c444359352fe148George Mount                        captureStartValues(values);
141530da61d477bcb6cc7718f9516c444359352fe148George Mount                    } else {
141630da61d477bcb6cc7718f9516c444359352fe148George Mount                        captureEndValues(values);
141730da61d477bcb6cc7718f9516c444359352fe148George Mount                    }
141830da61d477bcb6cc7718f9516c444359352fe148George Mount                    capturePropagationValues(values);
141930da61d477bcb6cc7718f9516c444359352fe148George Mount                    if (start) {
142030da61d477bcb6cc7718f9516c444359352fe148George Mount                        addViewValues(mStartValues, view, values);
142130da61d477bcb6cc7718f9516c444359352fe148George Mount                    } else {
142230da61d477bcb6cc7718f9516c444359352fe148George Mount                        addViewValues(mEndValues, view, values);
1423faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
1424faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1425faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
142630da61d477bcb6cc7718f9516c444359352fe148George Mount            for (int i = 0; i < mTargets.size(); ++i) {
142730da61d477bcb6cc7718f9516c444359352fe148George Mount                View view = mTargets.get(i);
142830da61d477bcb6cc7718f9516c444359352fe148George Mount                TransitionValues values = new TransitionValues();
142930da61d477bcb6cc7718f9516c444359352fe148George Mount                values.view = view;
143030da61d477bcb6cc7718f9516c444359352fe148George Mount                if (start) {
143130da61d477bcb6cc7718f9516c444359352fe148George Mount                    captureStartValues(values);
143230da61d477bcb6cc7718f9516c444359352fe148George Mount                } else {
143330da61d477bcb6cc7718f9516c444359352fe148George Mount                    captureEndValues(values);
143430da61d477bcb6cc7718f9516c444359352fe148George Mount                }
143530da61d477bcb6cc7718f9516c444359352fe148George Mount                capturePropagationValues(values);
143630da61d477bcb6cc7718f9516c444359352fe148George Mount                if (start) {
143730da61d477bcb6cc7718f9516c444359352fe148George Mount                    mStartValues.viewValues.put(view, values);
143830da61d477bcb6cc7718f9516c444359352fe148George Mount                } else {
143930da61d477bcb6cc7718f9516c444359352fe148George Mount                    mEndValues.viewValues.put(view, values);
1440faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1441faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1442faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1443faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            captureHierarchy(sceneRoot, start);
1444faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1445d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        if (!start && mNameOverrides != null) {
1446d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            int numOverrides = mNameOverrides.size();
1447d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            ArrayList<View> overriddenViews = new ArrayList<View>(numOverrides);
1448d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            for (int i = 0; i < numOverrides; i++) {
1449d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                String fromName = mNameOverrides.keyAt(i);
1450d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                overriddenViews.add(mStartValues.nameValues.remove(fromName));
1451d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            }
1452d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            for (int i = 0; i < numOverrides; i++) {
1453d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                View view = overriddenViews.get(i);
1454d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                if (view != null) {
1455d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                    String toName = mNameOverrides.valueAt(i);
1456d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                    mStartValues.nameValues.put(toName, view);
1457d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                }
1458d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            }
1459d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        }
1460faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1461faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
146230da61d477bcb6cc7718f9516c444359352fe148George Mount    static void addViewValues(TransitionValuesMaps transitionValuesMaps,
146330da61d477bcb6cc7718f9516c444359352fe148George Mount            View view, TransitionValues transitionValues) {
146430da61d477bcb6cc7718f9516c444359352fe148George Mount        transitionValuesMaps.viewValues.put(view, transitionValues);
146530da61d477bcb6cc7718f9516c444359352fe148George Mount        int id = view.getId();
146630da61d477bcb6cc7718f9516c444359352fe148George Mount        if (id >= 0) {
146730da61d477bcb6cc7718f9516c444359352fe148George Mount            if (transitionValuesMaps.idValues.indexOfKey(id) >= 0) {
146830da61d477bcb6cc7718f9516c444359352fe148George Mount                // Duplicate IDs cannot match by ID.
146930da61d477bcb6cc7718f9516c444359352fe148George Mount                transitionValuesMaps.idValues.put(id, null);
147030da61d477bcb6cc7718f9516c444359352fe148George Mount            } else {
147130da61d477bcb6cc7718f9516c444359352fe148George Mount                transitionValuesMaps.idValues.put(id, view);
147230da61d477bcb6cc7718f9516c444359352fe148George Mount            }
147330da61d477bcb6cc7718f9516c444359352fe148George Mount        }
14740a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount        String name = view.getTransitionName();
147530da61d477bcb6cc7718f9516c444359352fe148George Mount        if (name != null) {
147630da61d477bcb6cc7718f9516c444359352fe148George Mount            if (transitionValuesMaps.nameValues.containsKey(name)) {
14770a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount                // Duplicate transitionNames: cannot match by transitionName.
147830da61d477bcb6cc7718f9516c444359352fe148George Mount                transitionValuesMaps.nameValues.put(name, null);
147930da61d477bcb6cc7718f9516c444359352fe148George Mount            } else {
148030da61d477bcb6cc7718f9516c444359352fe148George Mount                transitionValuesMaps.nameValues.put(name, view);
148130da61d477bcb6cc7718f9516c444359352fe148George Mount            }
148230da61d477bcb6cc7718f9516c444359352fe148George Mount        }
148330da61d477bcb6cc7718f9516c444359352fe148George Mount        if (view.getParent() instanceof ListView) {
148430da61d477bcb6cc7718f9516c444359352fe148George Mount            ListView listview = (ListView) view.getParent();
148530da61d477bcb6cc7718f9516c444359352fe148George Mount            if (listview.getAdapter().hasStableIds()) {
148630da61d477bcb6cc7718f9516c444359352fe148George Mount                int position = listview.getPositionForView(view);
148730da61d477bcb6cc7718f9516c444359352fe148George Mount                long itemId = listview.getItemIdAtPosition(position);
148830da61d477bcb6cc7718f9516c444359352fe148George Mount                if (transitionValuesMaps.itemIdValues.indexOfKey(itemId) >= 0) {
148930da61d477bcb6cc7718f9516c444359352fe148George Mount                    // Duplicate item IDs: cannot match by item ID.
149030da61d477bcb6cc7718f9516c444359352fe148George Mount                    View alreadyMatched = transitionValuesMaps.itemIdValues.get(itemId);
149130da61d477bcb6cc7718f9516c444359352fe148George Mount                    if (alreadyMatched != null) {
149230da61d477bcb6cc7718f9516c444359352fe148George Mount                        alreadyMatched.setHasTransientState(false);
149330da61d477bcb6cc7718f9516c444359352fe148George Mount                        transitionValuesMaps.itemIdValues.put(itemId, null);
149430da61d477bcb6cc7718f9516c444359352fe148George Mount                    }
149530da61d477bcb6cc7718f9516c444359352fe148George Mount                } else {
149630da61d477bcb6cc7718f9516c444359352fe148George Mount                    view.setHasTransientState(true);
149730da61d477bcb6cc7718f9516c444359352fe148George Mount                    transitionValuesMaps.itemIdValues.put(itemId, view);
149830da61d477bcb6cc7718f9516c444359352fe148George Mount                }
149930da61d477bcb6cc7718f9516c444359352fe148George Mount            }
150030da61d477bcb6cc7718f9516c444359352fe148George Mount        }
150130da61d477bcb6cc7718f9516c444359352fe148George Mount    }
150230da61d477bcb6cc7718f9516c444359352fe148George Mount
1503faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1504df32aa87150768795816852c6393306893467ecaChet Haase     * Clear valuesMaps for specified start/end state
1505df32aa87150768795816852c6393306893467ecaChet Haase     *
1506df32aa87150768795816852c6393306893467ecaChet Haase     * @param start true if the start values should be cleared, false otherwise
1507df32aa87150768795816852c6393306893467ecaChet Haase     */
1508df32aa87150768795816852c6393306893467ecaChet Haase    void clearValues(boolean start) {
1509df32aa87150768795816852c6393306893467ecaChet Haase        if (start) {
1510df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.viewValues.clear();
1511df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.idValues.clear();
1512df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.itemIdValues.clear();
1513d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            mStartValues.nameValues.clear();
15144d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            mStartValuesList = null;
1515df32aa87150768795816852c6393306893467ecaChet Haase        } else {
1516df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.viewValues.clear();
1517df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.idValues.clear();
1518df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.itemIdValues.clear();
1519d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            mEndValues.nameValues.clear();
15204d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            mEndValuesList = null;
1521df32aa87150768795816852c6393306893467ecaChet Haase        }
1522df32aa87150768795816852c6393306893467ecaChet Haase    }
1523df32aa87150768795816852c6393306893467ecaChet Haase
1524df32aa87150768795816852c6393306893467ecaChet Haase    /**
1525faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Recursive method which captures values for an entire view hierarchy,
1526faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * starting at some root view. Transitions without targetIDs will use this
1527faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * method to capture values for all possible views.
1528faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1529faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param view The view for which to capture values. Children of this View
1530faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * will also be captured, recursively down to the leaf nodes.
1531faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param start true if values are being captured in the start scene, false
1532faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * otherwise.
1533faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1534faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    private void captureHierarchy(View view, boolean start) {
1535faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (view == null) {
1536faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            return;
1537faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
153830da61d477bcb6cc7718f9516c444359352fe148George Mount        int id = view.getId();
1539ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetIdExcludes != null && mTargetIdExcludes.contains(id)) {
1540ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return;
1541ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1542ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetExcludes != null && mTargetExcludes.contains(view)) {
1543ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return;
1544ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1545ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetTypeExcludes != null && view != null) {
1546ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            int numTypes = mTargetTypeExcludes.size();
1547ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            for (int i = 0; i < numTypes; ++i) {
1548ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (mTargetTypeExcludes.get(i).isInstance(view)) {
1549ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    return;
1550ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
1551ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1552ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1553e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount        if (view.getParent() instanceof ViewGroup) {
1554e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            TransitionValues values = new TransitionValues();
1555e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            values.view = view;
1556e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            if (start) {
1557e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                captureStartValues(values);
1558faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
1559e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                captureEndValues(values);
1560faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1561d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            capturePropagationValues(values);
1562e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            if (start) {
156330da61d477bcb6cc7718f9516c444359352fe148George Mount                addViewValues(mStartValues, view, values);
1564faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
156530da61d477bcb6cc7718f9516c444359352fe148George Mount                addViewValues(mEndValues, view, values);
1566faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1567faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1568faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (view instanceof ViewGroup) {
1569ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            // Don't traverse child hierarchy if there are any child-excludes on this view
1570ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (mTargetIdChildExcludes != null && mTargetIdChildExcludes.contains(id)) {
1571ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                return;
1572ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1573ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (mTargetChildExcludes != null && mTargetChildExcludes.contains(view)) {
1574ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                return;
1575ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
157630da61d477bcb6cc7718f9516c444359352fe148George Mount            if (mTargetTypeChildExcludes != null) {
1577ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                int numTypes = mTargetTypeChildExcludes.size();
1578ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                for (int i = 0; i < numTypes; ++i) {
1579ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    if (mTargetTypeChildExcludes.get(i).isInstance(view)) {
1580ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                        return;
1581ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    }
1582ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
1583ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1584faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            ViewGroup parent = (ViewGroup) view;
1585faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            for (int i = 0; i < parent.getChildCount(); ++i) {
1586faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                captureHierarchy(parent.getChildAt(i), start);
1587faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1588faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1589faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1590faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1591faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
15926ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * This method can be called by transitions to get the TransitionValues for
15936ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * any particular view during the transition-playing process. This might be
15946ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * necessary, for example, to query the before/after state of related views
15956ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * for a given transition.
15966ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     */
1597d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public TransitionValues getTransitionValues(View view, boolean start) {
15986ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        if (mParent != null) {
15996ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            return mParent.getTransitionValues(view, start);
16006ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        }
16016ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        TransitionValuesMaps valuesMaps = start ? mStartValues : mEndValues;
160230da61d477bcb6cc7718f9516c444359352fe148George Mount        return valuesMaps.viewValues.get(view);
16036ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
16046ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
16056ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    /**
16064d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * Find the matched start or end value for a given View. This is only valid
16074d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * after playTransition starts. For example, it will be valid in
16084d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}, but not
16094d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * in {@link #captureStartValues(TransitionValues)}.
16104d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     *
16114d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * @param view The view to find the match for.
16124d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * @param viewInStart Is View from the start values or end values.
16134d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * @return The matching TransitionValues for view in either start or end values, depending
16144d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * on viewInStart or null if there is no match for the given view.
16154d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     */
16164d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    TransitionValues getMatchedTransitionValues(View view, boolean viewInStart) {
16174d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        if (mParent != null) {
16184d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            return mParent.getMatchedTransitionValues(view, viewInStart);
16194d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        }
16204d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        ArrayList<TransitionValues> lookIn = viewInStart ? mStartValuesList : mEndValuesList;
16214d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        if (lookIn == null) {
16224d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            return null;
16234d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        }
16244d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        int count = lookIn.size();
16254d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        int index = -1;
16264d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        for (int i = 0; i < count; i++) {
16274d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            TransitionValues values = lookIn.get(i);
16284d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            if (values == null) {
16294d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                return null;
16304d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            }
16314d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            if (values.view == view) {
16324d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                index = i;
16334d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                break;
16344d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            }
16354d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        }
16364d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        TransitionValues values = null;
16374d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        if (index >= 0) {
16384d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            ArrayList<TransitionValues> matchIn = viewInStart ? mEndValuesList : mStartValuesList;
16394d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            values = matchIn.get(index);
16404d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        }
16414d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        return values;
16424d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    }
16434d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount
16444d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    /**
1645199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Pauses this transition, sending out calls to {@link
1646199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * TransitionListener#onTransitionPause(Transition)} to all listeners
1647199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * and pausing all running animators started by this transition.
1648199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1649199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @hide
1650199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
1651cf68aad3164303df59b2a669d186a94533c9c743George Mount    public void pause(View sceneRoot) {
1652a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase        if (!mEnded) {
1653a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1654a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            int numOldAnims = runningAnimators.size();
165551c014843a6d339d115dfa88b9ee2fff90a8b844George Mount            if (sceneRoot != null) {
165651c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                WindowId windowId = sceneRoot.getWindowId();
165751c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                for (int i = numOldAnims - 1; i >= 0; i--) {
165851c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                    AnimationInfo info = runningAnimators.valueAt(i);
16596276cd4b8defba1b6fef47ebc1bbe14498655b94George Mount                    if (info.view != null && windowId != null && windowId.equals(info.windowId)) {
166051c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                        Animator anim = runningAnimators.keyAt(i);
166151c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                        anim.pause();
166251c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                    }
1663cf68aad3164303df59b2a669d186a94533c9c743George Mount                }
1664a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            }
1665a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1666a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                ArrayList<TransitionListener> tmpListeners =
1667a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1668a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                int numListeners = tmpListeners.size();
1669a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                for (int i = 0; i < numListeners; ++i) {
1670a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    tmpListeners.get(i).onTransitionPause(this);
1671a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                }
1672199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1673a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mPaused = true;
1674199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1675199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1676199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1677199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1678199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Resumes this transition, sending out calls to {@link
1679199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * TransitionListener#onTransitionPause(Transition)} to all listeners
1680199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * and pausing all running animators started by this transition.
1681199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1682199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @hide
1683199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
1684cf68aad3164303df59b2a669d186a94533c9c743George Mount    public void resume(View sceneRoot) {
1685199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (mPaused) {
1686a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            if (!mEnded) {
1687a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1688a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                int numOldAnims = runningAnimators.size();
1689cf68aad3164303df59b2a669d186a94533c9c743George Mount                WindowId windowId = sceneRoot.getWindowId();
1690a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                for (int i = numOldAnims - 1; i >= 0; i--) {
1691cf68aad3164303df59b2a669d186a94533c9c743George Mount                    AnimationInfo info = runningAnimators.valueAt(i);
16926276cd4b8defba1b6fef47ebc1bbe14498655b94George Mount                    if (info.view != null && windowId != null && windowId.equals(info.windowId)) {
1693cf68aad3164303df59b2a669d186a94533c9c743George Mount                        Animator anim = runningAnimators.keyAt(i);
1694cf68aad3164303df59b2a669d186a94533c9c743George Mount                        anim.resume();
1695cf68aad3164303df59b2a669d186a94533c9c743George Mount                    }
1696a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                }
1697a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                if (mListeners != null && mListeners.size() > 0) {
1698a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    ArrayList<TransitionListener> tmpListeners =
1699a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                            (ArrayList<TransitionListener>) mListeners.clone();
1700a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    int numListeners = tmpListeners.size();
1701a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    for (int i = 0; i < numListeners; ++i) {
1702a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                        tmpListeners.get(i).onTransitionResume(this);
1703a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    }
1704199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                }
1705199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1706199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            mPaused = false;
1707199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1708199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1709199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1710199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1711faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Called by TransitionManager to play the transition. This calls
1712d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * createAnimators() to set things up and create all of the animations and then
17132ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * runAnimations() to actually start the animations.
1714faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
17156ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    void playTransition(ViewGroup sceneRoot) {
17164d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        mStartValuesList = new ArrayList<TransitionValues>();
17174d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        mEndValuesList = new ArrayList<TransitionValues>();
17184d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        matchStartAndEnd(mStartValues, mEndValues);
17194d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount
1720199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1721199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        int numOldAnims = runningAnimators.size();
1722fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        WindowId windowId = sceneRoot.getWindowId();
1723199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        for (int i = numOldAnims - 1; i >= 0; i--) {
1724199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            Animator anim = runningAnimators.keyAt(i);
1725199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            if (anim != null) {
1726199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                AnimationInfo oldInfo = runningAnimators.get(anim);
1727fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                if (oldInfo != null && oldInfo.view != null && oldInfo.windowId == windowId) {
1728199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    TransitionValues oldValues = oldInfo.values;
1729199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    View oldView = oldInfo.view;
17304d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                    TransitionValues newValues = getMatchedTransitionValues(oldView, true);
17314c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount                    boolean cancel = oldInfo.transition.areValuesChanged(oldValues, newValues);
1732199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    if (cancel) {
1733199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        if (anim.isRunning() || anim.isStarted()) {
1734199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            if (DBG) {
1735199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                Log.d(LOG_TAG, "Canceling anim " + anim);
1736199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
1737199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            anim.cancel();
1738199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        } else {
1739199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            if (DBG) {
1740199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                Log.d(LOG_TAG, "removing anim from info list: " + anim);
1741199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
1742199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            runningAnimators.remove(anim);
1743199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
1744199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    }
1745199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                }
1746199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1747199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1748199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
17494d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        createAnimators(sceneRoot, mStartValues, mEndValues, mStartValuesList, mEndValuesList);
1750d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        runAnimators();
1751faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1752faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
17534c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount    boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
17544c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        boolean valuesChanged = false;
17554c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        // if oldValues null, then transition didn't care to stash values,
17564c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        // and won't get canceled
17574c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        if (oldValues != null && newValues != null) {
1758c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu            String[] properties = getTransitionProperties();
1759c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu            if (properties != null) {
1760c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                int count = properties.length;
1761c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                for (int i = 0; i < count; i++) {
1762c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                    if (isValueChanged(oldValues, newValues, properties[i])) {
1763c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                        valuesChanged = true;
1764c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                        break;
1765c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                    }
1766c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                }
1767c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu            } else {
1768c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                for (String key : oldValues.values.keySet()) {
1769c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                    if (isValueChanged(oldValues, newValues, key)) {
1770c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                        valuesChanged = true;
1771c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                        break;
17724c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount                    }
17734c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount                }
17744c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount            }
17754c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        }
17764c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        return valuesChanged;
17774c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount    }
17784c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount
1779c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu    private static boolean isValueChanged(TransitionValues oldValues, TransitionValues newValues,
1780c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu            String key) {
1781c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu        Object oldValue = oldValues.values.get(key);
1782c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu        Object newValue = newValues.values.get(key);
1783c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu        boolean changed = (oldValue != null && newValue != null && !oldValue.equals(newValue));
1784c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu        if (DBG && changed) {
1785c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu            Log.d(LOG_TAG, "Transition.playTransition: " +
1786c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                    "oldValue != newValue for " + key +
1787c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                    ": old, new = " + oldValue + ", " + newValue);
1788c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu        }
1789c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu        return changed;
1790c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu    }
1791c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu
1792faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1793faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This is a utility method used by subclasses to handle standard parts of
1794faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * setting up and running an Animator: it sets the {@link #getDuration()
1795faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * duration} and the {@link #getStartDelay() startDelay}, starts the
1796199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animation, and, when the animator ends, calls {@link #end()}.
1797faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1798faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param animator The Animator to be run during this transition.
1799faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1800faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1801faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1802faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    protected void animate(Animator animator) {
1803faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        // TODO: maybe pass auto-end as a boolean parameter?
1804faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (animator == null) {
1805199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            end();
1806faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1807faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getDuration() >= 0) {
1808faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                animator.setDuration(getDuration());
1809faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1810faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getStartDelay() >= 0) {
1811d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                animator.setStartDelay(getStartDelay() + animator.getStartDelay());
1812faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1813faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getInterpolator() != null) {
1814faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                animator.setInterpolator(getInterpolator());
1815faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1816faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            animator.addListener(new AnimatorListenerAdapter() {
1817faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                @Override
1818faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                public void onAnimationEnd(Animator animation) {
1819199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    end();
1820faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    animation.removeListener(this);
1821faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1822faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            });
1823faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            animator.start();
1824faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1825faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1826faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1827faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1828faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method is called automatically by the transition and
1829d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * TransitionSet classes prior to a Transition subclass starting;
1830faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * subclasses should not need to call it directly.
1831faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1832faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1833faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1834199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void start() {
1835faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mNumInstances == 0) {
1836faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1837faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                ArrayList<TransitionListener> tmpListeners =
1838faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1839faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                int numListeners = tmpListeners.size();
1840faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                for (int i = 0; i < numListeners; ++i) {
1841faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    tmpListeners.get(i).onTransitionStart(this);
1842faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1843faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1844a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mEnded = false;
1845faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1846faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mNumInstances++;
1847faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1848faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1849faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1850faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method is called automatically by the Transition and
1851d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * TransitionSet classes when a transition finishes, either because
1852faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * a transition did nothing (returned a null Animator from
1853d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link Transition#createAnimator(ViewGroup, TransitionValues,
1854faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * TransitionValues)}) or because the transition returned a valid
1855199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Animator and end() was called in the onAnimationEnd()
1856faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * callback of the AnimatorListener.
1857faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1858faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1859faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1860199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void end() {
1861faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        --mNumInstances;
1862faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mNumInstances == 0) {
1863faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1864faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                ArrayList<TransitionListener> tmpListeners =
1865faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1866faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                int numListeners = tmpListeners.size();
1867faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                for (int i = 0; i < numListeners; ++i) {
1868faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    tmpListeners.get(i).onTransitionEnd(this);
1869faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1870faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
18716ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            for (int i = 0; i < mStartValues.itemIdValues.size(); ++i) {
187230da61d477bcb6cc7718f9516c444359352fe148George Mount                View view = mStartValues.itemIdValues.valueAt(i);
187330da61d477bcb6cc7718f9516c444359352fe148George Mount                if (view != null) {
187430da61d477bcb6cc7718f9516c444359352fe148George Mount                    view.setHasTransientState(false);
1875faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1876faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
18776ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            for (int i = 0; i < mEndValues.itemIdValues.size(); ++i) {
187830da61d477bcb6cc7718f9516c444359352fe148George Mount                View view = mEndValues.itemIdValues.valueAt(i);
187930da61d477bcb6cc7718f9516c444359352fe148George Mount                if (view != null) {
188030da61d477bcb6cc7718f9516c444359352fe148George Mount                    view.setHasTransientState(false);
1881faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1882faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1883a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mEnded = true;
1884faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1885faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1886faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1887faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1888faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method cancels a transition that is currently running.
1889d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
1890d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @hide
1891faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1892199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void cancel() {
1893e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        int numAnimators = mCurrentAnimators.size();
189425a738fb257aacfc87d3363a834ed6e0b050c3b1Chet Haase        for (int i = numAnimators - 1; i >= 0; i--) {
1895e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            Animator animator = mCurrentAnimators.get(i);
1896e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animator.cancel();
1897e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        }
1898faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners != null && mListeners.size() > 0) {
1899faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            ArrayList<TransitionListener> tmpListeners =
1900faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    (ArrayList<TransitionListener>) mListeners.clone();
1901faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            int numListeners = tmpListeners.size();
1902faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            for (int i = 0; i < numListeners; ++i) {
1903faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                tmpListeners.get(i).onTransitionCancel(this);
1904faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1905faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1906faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1907faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1908faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1909faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Adds a listener to the set of listeners that are sent events through the
1910faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * life of an animation, such as start, repeat, and end.
1911faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1912faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param listener the listener to be added to the current set of listeners
1913faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * for this animation.
1914d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
1915faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1916d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition addListener(TransitionListener listener) {
1917faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners == null) {
1918faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            mListeners = new ArrayList<TransitionListener>();
1919faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1920faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mListeners.add(listener);
1921d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
1922faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1923faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1924faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1925faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Removes a listener from the set listening to this animation.
1926faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1927faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param listener the listener to be removed from the current set of
1928faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listeners for this transition.
1929d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
1930faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1931d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition removeListener(TransitionListener listener) {
1932faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners == null) {
1933d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            return this;
1934faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1935faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mListeners.remove(listener);
1936faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners.size() == 0) {
1937faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            mListeners = null;
1938faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1939d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
1940faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1941faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1942d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1943d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Sets the callback to use to find the epicenter of a Transition. A null value indicates
1944dc21d3b2804c24fe29ec860796d11185901364c4George Mount     * that there is no epicenter in the Transition and onGetEpicenter() will return null.
1945d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Transitions like {@link android.transition.Explode} use a point or Rect to orient
1946d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the direction of travel. This is called the epicenter of the Transition and is
1947d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * typically centered on a touched View. The
1948d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
1949d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * dynamically retrieve the epicenter during a Transition.
1950d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param epicenterCallback The callback to use to find the epicenter of the Transition.
1951d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1952d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public void setEpicenterCallback(EpicenterCallback epicenterCallback) {
1953d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        mEpicenterCallback = epicenterCallback;
1954d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1955d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1956d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1957d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Returns the callback used to find the epicenter of the Transition.
1958d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Transitions like {@link android.transition.Explode} use a point or Rect to orient
1959d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the direction of travel. This is called the epicenter of the Transition and is
1960d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * typically centered on a touched View. The
1961d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
1962d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * dynamically retrieve the epicenter during a Transition.
1963d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return the callback used to find the epicenter of the Transition.
1964d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1965d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public EpicenterCallback getEpicenterCallback() {
1966d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        return mEpicenterCallback;
1967d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1968d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1969d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1970d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Returns the epicenter as specified by the
1971d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
1972d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return the epicenter as specified by the
1973d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
1974d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @see #setEpicenterCallback(android.transition.Transition.EpicenterCallback)
1975d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1976d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public Rect getEpicenter() {
1977d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (mEpicenterCallback == null) {
1978d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            return null;
1979d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
1980dc21d3b2804c24fe29ec860796d11185901364c4George Mount        return mEpicenterCallback.onGetEpicenter(this);
1981d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1982d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1983d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1984ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * Sets the algorithm used to calculate two-dimensional interpolation.
1985ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * <p>
1986ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *     Transitions such as {@link android.transition.ChangeBounds} move Views, typically
1987ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *     in a straight path between the start and end positions. Applications that desire to
1988ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *     have these motions move in a curve can change how Views interpolate in two dimensions
1989ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *     by extending PathMotion and implementing
1990ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *     {@link android.transition.PathMotion#getPath(float, float, float, float)}.
1991ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * </p>
1992ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * @param pathMotion Algorithm object to use for determining how to interpolate in two
1993ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *                   dimensions. If null, a straight-path algorithm will be used.
1994ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     */
1995ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    public void setPathMotion(PathMotion pathMotion) {
1996ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        if (pathMotion == null) {
1997ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            mPathMotion = STRAIGHT_PATH_MOTION;
1998ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        } else {
1999ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            mPathMotion = pathMotion;
2000ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        }
2001ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    }
2002ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
2003ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    /**
2004ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * Returns the algorithm object used to interpolate along two dimensions. This is typically
2005ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * used to determine the View motion between two points.
2006ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *
2007ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * @return The algorithm object used to interpolate along two dimensions.
2008ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     */
2009ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    public PathMotion getPathMotion() {
2010ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        return mPathMotion;
2011ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    }
2012ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
2013ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    /**
2014d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Sets the method for determining Animator start delays.
2015d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * When a Transition affects several Views like {@link android.transition.Explode} or
2016d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
2017d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * such that the Animator start delay depends on position of the View. The
2018d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * TransitionPropagation specifies how the start delays are calculated.
2019d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param transitionPropagation The class used to determine the start delay of
2020d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *                              Animators created by this Transition. A null value
2021d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *                              indicates that no delay should be used.
2022d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
2023d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public void setPropagation(TransitionPropagation transitionPropagation) {
2024d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        mPropagation = transitionPropagation;
2025d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
2026d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
2027d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
2028d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Returns the {@link android.transition.TransitionPropagation} used to calculate Animator start
2029d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * delays.
2030d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * When a Transition affects several Views like {@link android.transition.Explode} or
2031d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
2032d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * such that the Animator start delay depends on position of the View. The
2033d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * TransitionPropagation specifies how the start delays are calculated.
2034d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return the {@link android.transition.TransitionPropagation} used to calculate Animator start
2035d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * delays. This is null by default.
2036d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
2037d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public TransitionPropagation getPropagation() {
2038d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        return mPropagation;
2039d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
2040d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
2041d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
2042d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Captures TransitionPropagation values for the given view and the
2043d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * hierarchy underneath it.
2044d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
2045d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    void capturePropagationValues(TransitionValues transitionValues) {
204631a217290cf376d0573fc36e21c8940987485019George Mount        if (mPropagation != null && !transitionValues.values.isEmpty()) {
2047d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            String[] propertyNames = mPropagation.getPropagationProperties();
2048d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (propertyNames == null) {
2049d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                return;
2050d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
2051d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            boolean containsAll = true;
2052d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            for (int i = 0; i < propertyNames.length; i++) {
2053d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                if (!transitionValues.values.containsKey(propertyNames[i])) {
2054d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    containsAll = false;
2055d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    break;
2056d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                }
2057d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
2058d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (!containsAll) {
2059d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                mPropagation.captureValues(transitionValues);
2060d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
2061d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
2062d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
2063d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
2064d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    Transition setSceneRoot(ViewGroup sceneRoot) {
20656ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        mSceneRoot = sceneRoot;
2066d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
20676ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
20686ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
2069b7a7fc9d233bad507ce893882352618b13647058Chet Haase    void setCanRemoveViews(boolean canRemoveViews) {
2070b7a7fc9d233bad507ce893882352618b13647058Chet Haase        mCanRemoveViews = canRemoveViews;
2071b7a7fc9d233bad507ce893882352618b13647058Chet Haase    }
2072b7a7fc9d233bad507ce893882352618b13647058Chet Haase
20730a778eda690a66173733a63622886e888d405c45George Mount    public boolean canRemoveViews() {
20740a778eda690a66173733a63622886e888d405c45George Mount        return mCanRemoveViews;
20750a778eda690a66173733a63622886e888d405c45George Mount    }
20760a778eda690a66173733a63622886e888d405c45George Mount
2077d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    /**
2078d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount     * Sets the shared element names -- a mapping from a name at the start state to
2079d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount     * a different name at the end state.
2080d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount     * @hide
2081d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount     */
2082d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    public void setNameOverrides(ArrayMap<String, String> overrides) {
2083d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        mNameOverrides = overrides;
2084d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    }
2085d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount
2086d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    /** @hide */
2087d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    public ArrayMap<String, String> getNameOverrides() {
2088d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        return mNameOverrides;
2089d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    }
2090d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount
2091b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    /** @hide */
2092b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    public void forceVisibility(int visibility, boolean isStartValue) {}
2093b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount
2094faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    @Override
2095faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public String toString() {
2096faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return toString("");
2097faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
2098faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
20996ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    @Override
21006ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    public Transition clone() {
21016ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        Transition clone = null;
21026ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        try {
21036ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            clone = (Transition) super.clone();
2104199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            clone.mAnimators = new ArrayList<Animator>();
21057660d121b2ef21164ed33e6091e5dd50f5d0f939Chet Haase            clone.mStartValues = new TransitionValuesMaps();
21067660d121b2ef21164ed33e6091e5dd50f5d0f939Chet Haase            clone.mEndValues = new TransitionValuesMaps();
21074d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            clone.mStartValuesList = null;
21084d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            clone.mEndValuesList = null;
21096ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        } catch (CloneNotSupportedException e) {}
21106ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
21116ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        return clone;
21126ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
21136ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
2114199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
2115199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the name of this Transition. This name is used internally to distinguish
2116199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * between different transitions to determine when interrupting transitions overlap.
2117d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * For example, a ChangeBounds running on the same target view as another ChangeBounds
2118d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * should determine whether the old transition is animating to different end values
2119d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * and should be canceled in favor of the new transition.
2120199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
2121199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * <p>By default, a Transition's name is simply the value of {@link Class#getName()},
2122199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * but subclasses are free to override and return something different.</p>
2123199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
2124199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return The name of this transition.
2125199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
2126199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public String getName() {
2127199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return mName;
2128199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
2129199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
2130faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    String toString(String indent) {
2131faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        String result = indent + getClass().getSimpleName() + "@" +
2132faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                Integer.toHexString(hashCode()) + ": ";
2133c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mDuration != -1) {
2134c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "dur(" + mDuration + ") ";
2135c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
2136c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mStartDelay != -1) {
2137c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "dly(" + mStartDelay + ") ";
2138c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
2139c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mInterpolator != null) {
2140c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "interp(" + mInterpolator + ") ";
2141c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
2142d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (mTargetIds.size() > 0 || mTargets.size() > 0) {
2143c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "tgts(";
2144d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargetIds.size() > 0) {
2145d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargetIds.size(); ++i) {
2146c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (i > 0) {
2147c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        result += ", ";
2148c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
2149d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    result += mTargetIds.get(i);
2150faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
2151faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
2152d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargets.size() > 0) {
2153d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargets.size(); ++i) {
2154c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (i > 0) {
2155c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        result += ", ";
2156c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
2157d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    result += mTargets.get(i);
2158faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
2159faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
2160c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += ")";
2161faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
2162faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return result;
2163faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
2164faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2165faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
2166faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * A transition listener receives notifications from a transition.
2167199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Notifications indicate transition lifecycle events.
2168faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
2169faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public static interface TransitionListener {
2170faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
2171faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the start of the transition.
2172faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
2173faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The started transition.
2174faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
2175faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionStart(Transition transition);
2176faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2177faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
2178faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the end of the transition. Canceled transitions
2179faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * will always notify listeners of both the cancellation and end
2180199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * events. That is, {@link #onTransitionEnd(Transition)} is always called,
2181faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * regardless of whether the transition was canceled or played
2182faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * through to completion.
2183faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
2184faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The transition which reached its end.
2185faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
2186faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionEnd(Transition transition);
2187faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2188faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
2189faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the cancellation of the transition.
2190d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that cancel may be called by a parent {@link TransitionSet} on
2191199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
2192199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state on target objects which was set at
2193d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
2194d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * createAnimator()} time.
2195faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
2196faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The transition which was canceled.
2197faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
2198faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionCancel(Transition transition);
2199199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
2200199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        /**
2201199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * Notification when a transition is paused.
2202d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that createAnimator() may be called by a parent {@link TransitionSet} on
2203199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
2204199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state on target objects which was set at
2205d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
2206d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * createAnimator()} time.
2207199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         *
2208199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * @param transition The transition which was paused.
2209199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         */
2210199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        void onTransitionPause(Transition transition);
2211199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
2212199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        /**
2213199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * Notification when a transition is resumed.
2214d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that resume() may be called by a parent {@link TransitionSet} on
2215199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
2216199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state which may have changed in an earlier call
2217199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * to {@link #onTransitionPause(Transition)}.
2218199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         *
2219199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * @param transition The transition which was resumed.
2220199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         */
2221199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        void onTransitionResume(Transition transition);
2222faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
2223faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2224faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
2225faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Utility adapter class to avoid having to override all three methods
2226faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * whenever someone just wants to listen for a single event.
2227faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
2228faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
2229faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * */
2230faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public static class TransitionListenerAdapter implements TransitionListener {
2231faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
2232faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionStart(Transition transition) {
2233faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
2234faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2235faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
2236faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionEnd(Transition transition) {
2237faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
2238faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2239faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
2240faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionCancel(Transition transition) {
2241faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
2242199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
2243199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        @Override
2244199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        public void onTransitionPause(Transition transition) {
2245199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
2246199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
2247199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        @Override
2248199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        public void onTransitionResume(Transition transition) {
2249199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
2250faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
2251faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2252199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
2253199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Holds information about each animator used when a new transition starts
2254199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * while other transitions are still running to determine whether a running
2255199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animation should be canceled or a new animation noop'd. The structure holds
2256199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * information about the state that an animation is going to, to be compared to
2257199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * end state of a new animation.
22580a778eda690a66173733a63622886e888d405c45George Mount     * @hide
2259199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
22600a778eda690a66173733a63622886e888d405c45George Mount    public static class AnimationInfo {
22610a778eda690a66173733a63622886e888d405c45George Mount        public View view;
2262199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        String name;
2263199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        TransitionValues values;
2264cf68aad3164303df59b2a669d186a94533c9c743George Mount        WindowId windowId;
22654c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        Transition transition;
2266199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
22674c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        AnimationInfo(View view, String name, Transition transition,
22684c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount                WindowId windowId, TransitionValues values) {
2269199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.view = view;
2270199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.name = name;
2271199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.values = values;
2272cf68aad3164303df59b2a669d186a94533c9c743George Mount            this.windowId = windowId;
22734c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount            this.transition = transition;
2274199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
2275199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
2276ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
2277ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
2278ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility class for managing typed ArrayLists efficiently. In particular, this
2279ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * can be useful for lists that we don't expect to be used often (eg, the exclude
2280ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * lists), so we'd like to keep them nulled out by default. This causes the code to
2281ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * become tedious, with constant null checks, code to allocate when necessary,
2282ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * and code to null out the reference when the list is empty. This class encapsulates
2283ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * all of that functionality into simple add()/remove() methods which perform the
2284ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * necessary checks, allocation/null-out as appropriate, and return the
2285ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * resulting list.
2286ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
2287ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    private static class ArrayListManager {
2288ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
2289ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        /**
2290ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Add the specified item to the list, returning the resulting list.
2291ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * The returned list can either the be same list passed in or, if that
2292ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list was null, the new list that was created.
2293ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         *
2294ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Note that the list holds unique items; if the item already exists in the
2295ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list, the list is not modified.
2296ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         */
2297ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        static <T> ArrayList<T> add(ArrayList<T> list, T item) {
2298ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (list == null) {
2299ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = new ArrayList<T>();
2300ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
2301ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (!list.contains(item)) {
2302ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list.add(item);
2303ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
2304ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return list;
2305ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
2306ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
2307ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        /**
2308ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Remove the specified item from the list, returning the resulting list.
2309ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * The returned list can either the be same list passed in or, if that
2310ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list becomes empty as a result of the remove(), the new list was created.
2311ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         */
2312ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        static <T> ArrayList<T> remove(ArrayList<T> list, T item) {
2313ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (list != null) {
2314ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list.remove(item);
2315ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (list.isEmpty()) {
2316ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    list = null;
2317ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
2318ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
2319ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return list;
2320ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
2321ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
2322ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
2323d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
2324d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Class to get the epicenter of Transition. Use
2325d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #setEpicenterCallback(android.transition.Transition.EpicenterCallback)} to
2326d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * set the callback used to calculate the epicenter of the Transition. Override
2327d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #getEpicenter()} to return the rectangular region in screen coordinates of
2328d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the epicenter of the transition.
2329d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @see #setEpicenterCallback(android.transition.Transition.EpicenterCallback)
2330d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
2331d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public static abstract class EpicenterCallback {
2332d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
2333d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        /**
2334d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * Implementers must override to return the epicenter of the Transition in screen
2335d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * coordinates. Transitions like {@link android.transition.Explode} depend upon
2336d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * an epicenter for the Transition. In Explode, Views move toward or away from the
2337d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * center of the epicenter Rect along the vector between the epicenter and the center
2338d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * of the View appearing and disappearing. Some Transitions, such as
2339d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * {@link android.transition.Fade} pay no attention to the epicenter.
2340d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         *
2341d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * @param transition The transition for which the epicenter applies.
2342d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * @return The Rect region of the epicenter of <code>transition</code> or null if
2343d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * there is no epicenter.
2344d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         */
2345dc21d3b2804c24fe29ec860796d11185901364c4George Mount        public abstract Rect onGetEpicenter(Transition transition);
2346d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
2347faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase}
2348