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>
87b592d845147f051613fb62896b4e893015f8c413George Mount * <p>Custom transition classes loaded from XML should have a public constructor taking
88b592d845147f051613fb62896b4e893015f8c413George Mount * a {@link android.content.Context} and {@link android.util.AttributeSet}.</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);
6935030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            if (start != null && !start.targetedTransitions.contains(this)) {
6945030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                start = null;
6955030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            }
6965030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            if (end != null && !end.targetedTransitions.contains(this)) {
6975030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                end = null;
6985030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            }
6995030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            if (start == null && end == null) {
7005030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                continue;
7015030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            }
7025030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            // Only bother trying to animate with values that differ between start/end
7035030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            boolean isChanged = start == null || end == null || areValuesChanged(start, end);
7045030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            if (isChanged) {
705208dcade9373905b7168feb24db141cd71c45159George Mount                if (DBG) {
706208dcade9373905b7168feb24db141cd71c45159George Mount                    View view = (end != null) ? end.view : start.view;
707208dcade9373905b7168feb24db141cd71c45159George Mount                    Log.d(LOG_TAG, "  differing start/end values for view " + view);
708208dcade9373905b7168feb24db141cd71c45159George Mount                    if (start == null || end == null) {
709208dcade9373905b7168feb24db141cd71c45159George Mount                        Log.d(LOG_TAG, "    " + ((start == null) ?
710208dcade9373905b7168feb24db141cd71c45159George Mount                                "start null, end non-null" : "start non-null, end null"));
711208dcade9373905b7168feb24db141cd71c45159George Mount                    } else {
712208dcade9373905b7168feb24db141cd71c45159George Mount                        for (String key : start.values.keySet()) {
713208dcade9373905b7168feb24db141cd71c45159George Mount                            Object startValue = start.values.get(key);
714208dcade9373905b7168feb24db141cd71c45159George Mount                            Object endValue = end.values.get(key);
715208dcade9373905b7168feb24db141cd71c45159George Mount                            if (startValue != endValue && !startValue.equals(endValue)) {
716208dcade9373905b7168feb24db141cd71c45159George Mount                                Log.d(LOG_TAG, "    " + key + ": start(" + startValue +
717208dcade9373905b7168feb24db141cd71c45159George Mount                                        "), end(" + endValue + ")");
718c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                            }
719c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        }
720c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
721208dcade9373905b7168feb24db141cd71c45159George Mount                }
722208dcade9373905b7168feb24db141cd71c45159George Mount                // TODO: what to do about targetIds and itemIds?
723208dcade9373905b7168feb24db141cd71c45159George Mount                Animator animator = createAnimator(sceneRoot, start, end);
724208dcade9373905b7168feb24db141cd71c45159George Mount                if (animator != null) {
725208dcade9373905b7168feb24db141cd71c45159George Mount                    // Save animation info for future cancellation purposes
726208dcade9373905b7168feb24db141cd71c45159George Mount                    View view = null;
727208dcade9373905b7168feb24db141cd71c45159George Mount                    TransitionValues infoValues = null;
728208dcade9373905b7168feb24db141cd71c45159George Mount                    if (end != null) {
729208dcade9373905b7168feb24db141cd71c45159George Mount                        view = end.view;
730208dcade9373905b7168feb24db141cd71c45159George Mount                        String[] properties = getTransitionProperties();
731208dcade9373905b7168feb24db141cd71c45159George Mount                        if (view != null && properties != null && properties.length > 0) {
732208dcade9373905b7168feb24db141cd71c45159George Mount                            infoValues = new TransitionValues();
733208dcade9373905b7168feb24db141cd71c45159George Mount                            infoValues.view = view;
734208dcade9373905b7168feb24db141cd71c45159George Mount                            TransitionValues newValues = endValues.viewValues.get(view);
735208dcade9373905b7168feb24db141cd71c45159George Mount                            if (newValues != null) {
736208dcade9373905b7168feb24db141cd71c45159George Mount                                for (int j = 0; j < properties.length; ++j) {
737208dcade9373905b7168feb24db141cd71c45159George Mount                                    infoValues.values.put(properties[j],
738208dcade9373905b7168feb24db141cd71c45159George Mount                                            newValues.values.get(properties[j]));
739199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                }
740208dcade9373905b7168feb24db141cd71c45159George Mount                            }
741208dcade9373905b7168feb24db141cd71c45159George Mount                            int numExistingAnims = runningAnimators.size();
742208dcade9373905b7168feb24db141cd71c45159George Mount                            for (int j = 0; j < numExistingAnims; ++j) {
743208dcade9373905b7168feb24db141cd71c45159George Mount                                Animator anim = runningAnimators.keyAt(j);
744208dcade9373905b7168feb24db141cd71c45159George Mount                                AnimationInfo info = runningAnimators.get(anim);
745208dcade9373905b7168feb24db141cd71c45159George Mount                                if (info.values != null && info.view == view &&
746208dcade9373905b7168feb24db141cd71c45159George Mount                                        ((info.name == null && getName() == null) ||
747208dcade9373905b7168feb24db141cd71c45159George Mount                                                info.name.equals(getName()))) {
748208dcade9373905b7168feb24db141cd71c45159George Mount                                    if (info.values.equals(infoValues)) {
749208dcade9373905b7168feb24db141cd71c45159George Mount                                        // Favor the old animator
750208dcade9373905b7168feb24db141cd71c45159George Mount                                        animator = null;
751208dcade9373905b7168feb24db141cd71c45159George Mount                                        break;
752199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                    }
753199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                }
754199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
755199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
756208dcade9373905b7168feb24db141cd71c45159George Mount                    } else {
757208dcade9373905b7168feb24db141cd71c45159George Mount                        view = (start != null) ? start.view : null;
758208dcade9373905b7168feb24db141cd71c45159George Mount                    }
759208dcade9373905b7168feb24db141cd71c45159George Mount                    if (animator != null) {
760208dcade9373905b7168feb24db141cd71c45159George Mount                        if (mPropagation != null) {
761208dcade9373905b7168feb24db141cd71c45159George Mount                            long delay = mPropagation
762208dcade9373905b7168feb24db141cd71c45159George Mount                                    .getStartDelay(sceneRoot, this, start, end);
763208dcade9373905b7168feb24db141cd71c45159George Mount                            startDelays.put(mAnimators.size(), delay);
764208dcade9373905b7168feb24db141cd71c45159George Mount                            minStartDelay = Math.min(delay, minStartDelay);
765199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
7664c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount                        AnimationInfo info = new AnimationInfo(view, getName(), this,
767208dcade9373905b7168feb24db141cd71c45159George Mount                                sceneRoot.getWindowId(), infoValues);
768208dcade9373905b7168feb24db141cd71c45159George Mount                        runningAnimators.put(animator, info);
769208dcade9373905b7168feb24db141cd71c45159George Mount                        mAnimators.add(animator);
770c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
771c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                }
772faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
773faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
774d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (minStartDelay != 0) {
775d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            for (int i = 0; i < startDelays.size(); i++) {
776d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                int index = startDelays.keyAt(i);
777d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                Animator animator = mAnimators.get(index);
778d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                long delay = startDelays.valueAt(i) - minStartDelay + animator.getStartDelay();
779d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                animator.setStartDelay(delay);
780d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
781d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
782faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
783faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
784faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
785faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Internal utility method for checking whether a given view/id
786faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * is valid for this transition, where "valid" means that either
787faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition has no target/targetId list (the default, in which
788faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * cause the transition should act on all views in the hiearchy), or
789faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the given view is in the target list or the view id is in the
790faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * targetId list. If the target parameter is null, then the target list
791faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * is not checked (this is in the case of ListView items, where the
792faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * views are ignored and only the ids are used).
793faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
79430da61d477bcb6cc7718f9516c444359352fe148George Mount    boolean isValidTarget(View target) {
79530da61d477bcb6cc7718f9516c444359352fe148George Mount        int targetId = target.getId();
796ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetIdExcludes != null && mTargetIdExcludes.contains(targetId)) {
797ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return false;
798ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
799ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetExcludes != null && mTargetExcludes.contains(target)) {
800ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return false;
801ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
802ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetTypeExcludes != null && target != null) {
803ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            int numTypes = mTargetTypeExcludes.size();
804ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            for (int i = 0; i < numTypes; ++i) {
805ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                Class type = mTargetTypeExcludes.get(i);
806ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (type.isInstance(target)) {
807ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    return false;
808ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
809ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
810ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
8110a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount        if (mTargetNameExcludes != null && target != null && target.getTransitionName() != null) {
8120a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount            if (mTargetNameExcludes.contains(target.getTransitionName())) {
81330da61d477bcb6cc7718f9516c444359352fe148George Mount                return false;
81430da61d477bcb6cc7718f9516c444359352fe148George Mount            }
81530da61d477bcb6cc7718f9516c444359352fe148George Mount        }
81630da61d477bcb6cc7718f9516c444359352fe148George Mount        if (mTargetIds.size() == 0 && mTargets.size() == 0 &&
817cc82424b449f9d106d8d4caee74ad869d0e620ceGeorge Mount                (mTargetTypes == null || mTargetTypes.isEmpty()) &&
818cc82424b449f9d106d8d4caee74ad869d0e620ceGeorge Mount                (mTargetNames == null || mTargetNames.isEmpty())) {
81930da61d477bcb6cc7718f9516c444359352fe148George Mount            return true;
82030da61d477bcb6cc7718f9516c444359352fe148George Mount        }
82130da61d477bcb6cc7718f9516c444359352fe148George Mount        if (mTargetIds.contains(targetId) || mTargets.contains(target)) {
822faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            return true;
823faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
8240a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount        if (mTargetNames != null && mTargetNames.contains(target.getTransitionName())) {
825a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount            return true;
826faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
827a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount        if (mTargetTypes != null) {
828a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount            for (int i = 0; i < mTargetTypes.size(); ++i) {
829a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount                if (mTargetTypes.get(i).isInstance(target)) {
830faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    return true;
831faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
832faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
833faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
834faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return false;
835faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
836faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
837e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount    private static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
838199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = sRunningAnimators.get();
839199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (runningAnimators == null) {
840199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            runningAnimators = new ArrayMap<Animator, AnimationInfo>();
841199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            sRunningAnimators.set(runningAnimators);
842199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
843199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return runningAnimators;
844199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
845199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
846faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
8472ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * This is called internally once all animations have been set up by the
848d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * transition hierarchy.
849faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
850faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
851faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
852d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    protected void runAnimators() {
853199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (DBG) {
854d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            Log.d(LOG_TAG, "runAnimators() on " + this);
855199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
856199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        start();
857199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
858d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        // Now start every Animator that was previously created for this transition
859199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        for (Animator anim : mAnimators) {
860c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            if (DBG) {
861c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                Log.d(LOG_TAG, "  anim: " + anim);
862c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            }
863199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            if (runningAnimators.containsKey(anim)) {
864199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                start();
865199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                runAnimator(anim, runningAnimators);
866199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
867faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
868199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        mAnimators.clear();
869199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        end();
870faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
871faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
872199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    private void runAnimator(Animator animator,
873199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            final ArrayMap<Animator, AnimationInfo> runningAnimators) {
874e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        if (animator != null) {
875e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            // TODO: could be a single listener instance for all of them since it uses the param
876e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animator.addListener(new AnimatorListenerAdapter() {
877e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                @Override
878e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                public void onAnimationStart(Animator animation) {
879e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                    mCurrentAnimators.add(animation);
880e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                }
881e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                @Override
882e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                public void onAnimationEnd(Animator animation) {
883199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    runningAnimators.remove(animation);
884e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                    mCurrentAnimators.remove(animation);
885e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase                }
886e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            });
887e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animate(animator);
888e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        }
889e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase    }
890e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase
891faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
892d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Captures the values in the start scene for the properties that this
893d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition monitors. These values are then passed as the startValues
894d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * structure in a later call to
895d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
896d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The main concern for an implementation is what the
897d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * properties are that the transition cares about and what the values are
898d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * for all of those properties. The start and end values will be compared
899d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * later during the
900d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}
901d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * method to determine what, if any, animations, should be run.
902d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
903d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Subclasses must implement this method. The method should only be called by the
904d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition system; it is not intended to be called from external classes.</p>
905d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
906d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param transitionValues The holder for any values that the Transition
907d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * wishes to store. Values are stored in the <code>values</code> field
908d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * of this TransitionValues object and are keyed from
909d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * a String value. For example, to store a view's rotation value,
910d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * a transition might call
911d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionValues.values.put("appname:transitionname:rotation",
912d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * view.getRotation())</code>. The target view will already be stored in
913d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * the transitionValues structure when this method is called.
914d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
915d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #captureEndValues(TransitionValues)
916d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
917d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
918d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public abstract void captureStartValues(TransitionValues transitionValues);
919d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
920d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
921d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Captures the values in the end scene for the properties that this
922d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition monitors. These values are then passed as the endValues
923d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * structure in a later call to
924d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
925d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The main concern for an implementation is what the
926faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * properties are that the transition cares about and what the values are
927faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * for all of those properties. The start and end values will be compared
9282ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * later during the
929d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}
9302ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * method to determine what, if any, animations, should be run.
931faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
932d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Subclasses must implement this method. The method should only be called by the
933d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * transition system; it is not intended to be called from external classes.</p>
934d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
9352ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * @param transitionValues The holder for any values that the Transition
9362ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * wishes to store. Values are stored in the <code>values</code> field
9372ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * of this TransitionValues object and are keyed from
9382ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * a String value. For example, to store a view's rotation value,
9392ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * a transition might call
9402ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * <code>transitionValues.values.put("appname:transitionname:rotation",
9412ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * view.getRotation())</code>. The target view will already be stored in
9422ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * the transitionValues structure when this method is called.
943d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
944d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #captureStartValues(TransitionValues)
945d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
946faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
947d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public abstract void captureEndValues(TransitionValues transitionValues);
948faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
949faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
950d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Adds the id of a target view that this Transition is interested in
951faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * animating. By default, there are no targetIds, and a Transition will
952faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listen for changes on every view in the hierarchy below the sceneRoot
953d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * of the Scene being transitioned into. Setting targetIds constrains
954faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition to only listen for, and act on, views with these IDs.
955faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Views with different IDs, or no IDs whatsoever, will be ignored.
956faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
957d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <p>Note that using ids to specify targets implies that ids should be unique
958b592d845147f051613fb62896b4e893015f8c413George Mount     * within the view hierarchy underneath the scene root.</p>
959d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
960faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @see View#getId()
961d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param targetId The id of a target view, must be a positive number.
962d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition to which the targetId is added.
963d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Returning the same object makes it easier to chain calls during
964d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * construction, such as
965ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <code>transitionSet.addTransitions(new Fade()).addTarget(someId);</code>
966d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
967ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition addTarget(int targetId) {
968d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (targetId > 0) {
969d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargetIds.add(targetId);
970d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
971d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
972d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
973d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
974d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
9750a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Adds the transitionName of a target view that this Transition is interested in
97630da61d477bcb6cc7718f9516c444359352fe148George Mount     * animating. By default, there are no targetNames, and a Transition will
97730da61d477bcb6cc7718f9516c444359352fe148George Mount     * listen for changes on every view in the hierarchy below the sceneRoot
97830da61d477bcb6cc7718f9516c444359352fe148George Mount     * of the Scene being transitioned into. Setting targetNames constrains
9790a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * the Transition to only listen for, and act on, views with these transitionNames.
9800a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Views with different transitionNames, or no transitionName whatsoever, will be ignored.
98130da61d477bcb6cc7718f9516c444359352fe148George Mount     *
9820a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * <p>Note that transitionNames should be unique within the view hierarchy.</p>
98330da61d477bcb6cc7718f9516c444359352fe148George Mount     *
9840a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @see android.view.View#getTransitionName()
9850a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @param targetName The transitionName of a target view, must be non-null.
9860a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @return The Transition to which the target transitionName is added.
98730da61d477bcb6cc7718f9516c444359352fe148George Mount     * Returning the same object makes it easier to chain calls during
98830da61d477bcb6cc7718f9516c444359352fe148George Mount     * construction, such as
98930da61d477bcb6cc7718f9516c444359352fe148George Mount     * <code>transitionSet.addTransitions(new Fade()).addTarget(someName);</code>
99030da61d477bcb6cc7718f9516c444359352fe148George Mount     */
99130da61d477bcb6cc7718f9516c444359352fe148George Mount    public Transition addTarget(String targetName) {
99230da61d477bcb6cc7718f9516c444359352fe148George Mount        if (targetName != null) {
99358bbdbd1f1e2b2ed2e82caad6de6411fa2380cdcGeorge Mount            if (mTargetNames == null) {
99430da61d477bcb6cc7718f9516c444359352fe148George Mount                mTargetNames = new ArrayList<String>();
99530da61d477bcb6cc7718f9516c444359352fe148George Mount            }
99630da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetNames.add(targetName);
99730da61d477bcb6cc7718f9516c444359352fe148George Mount        }
99830da61d477bcb6cc7718f9516c444359352fe148George Mount        return this;
99930da61d477bcb6cc7718f9516c444359352fe148George Mount    }
100030da61d477bcb6cc7718f9516c444359352fe148George Mount
100130da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
1002a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * Adds the Class of a target view that this Transition is interested in
1003a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * animating. By default, there are no targetTypes, and a Transition will
1004a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * listen for changes on every view in the hierarchy below the sceneRoot
1005a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * of the Scene being transitioned into. Setting targetTypes constrains
1006a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * the Transition to only listen for, and act on, views with these classes.
1007a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * Views with different classes will be ignored.
1008a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     *
1009a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * <p>Note that any View that can be cast to targetType will be included, so
1010a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * if targetType is <code>View.class</code>, all Views will be included.</p>
1011a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     *
1012a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @see #addTarget(int)
1013a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @see #addTarget(android.view.View)
1014a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @see #excludeTarget(Class, boolean)
1015a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @see #excludeChildren(Class, boolean)
1016a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     *
1017a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @param targetType The type to include when running this transition.
1018a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * @return The Transition to which the target class was added.
1019a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * Returning the same object makes it easier to chain calls during
1020a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * construction, such as
1021a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     * <code>transitionSet.addTransitions(new Fade()).addTarget(ImageView.class);</code>
1022a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount     */
1023a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount    public Transition addTarget(Class targetType) {
102430da61d477bcb6cc7718f9516c444359352fe148George Mount        if (targetType != null) {
102530da61d477bcb6cc7718f9516c444359352fe148George Mount            if (mTargetTypes == null) {
102630da61d477bcb6cc7718f9516c444359352fe148George Mount                mTargetTypes = new ArrayList<Class>();
102730da61d477bcb6cc7718f9516c444359352fe148George Mount            }
102830da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetTypes.add(targetType);
1029a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount        }
1030a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount        return this;
1031a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount    }
1032a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount
1033a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount    /**
1034d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Removes the given targetId from the list of ids that this Transition
1035d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * is interested in animating.
1036d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
1037d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param targetId The id of a target view, must be a positive number.
1038d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition from which the targetId is removed.
1039faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returning the same object makes it easier to chain calls during
1040faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * construction, such as
1041d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).removeTargetId(someId);</code>
1042faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1043ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition removeTarget(int targetId) {
1044d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (targetId > 0) {
1045d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargetIds.remove(targetId);
1046d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
1047faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return this;
1048faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1049faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1050faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
10510a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Removes the given targetName from the list of transitionNames that this Transition
105230da61d477bcb6cc7718f9516c444359352fe148George Mount     * is interested in animating.
105330da61d477bcb6cc7718f9516c444359352fe148George Mount     *
10540a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @param targetName The transitionName of a target view, must not be null.
105530da61d477bcb6cc7718f9516c444359352fe148George Mount     * @return The Transition from which the targetName is removed.
105630da61d477bcb6cc7718f9516c444359352fe148George Mount     * Returning the same object makes it easier to chain calls during
105730da61d477bcb6cc7718f9516c444359352fe148George Mount     * construction, such as
105830da61d477bcb6cc7718f9516c444359352fe148George Mount     * <code>transitionSet.addTransitions(new Fade()).removeTargetName(someName);</code>
105930da61d477bcb6cc7718f9516c444359352fe148George Mount     */
106030da61d477bcb6cc7718f9516c444359352fe148George Mount    public Transition removeTarget(String targetName) {
106130da61d477bcb6cc7718f9516c444359352fe148George Mount        if (targetName != null && mTargetNames != null) {
106230da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetNames.remove(targetName);
106330da61d477bcb6cc7718f9516c444359352fe148George Mount        }
106430da61d477bcb6cc7718f9516c444359352fe148George Mount        return this;
106530da61d477bcb6cc7718f9516c444359352fe148George Mount    }
106630da61d477bcb6cc7718f9516c444359352fe148George Mount
106730da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
1068ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given id to the list of target ids to exclude from this
1069ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
1070ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should be added to or removed from the excluded list.
1071ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1072ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1073ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1074ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1075ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1076ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1077ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1078ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1079ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
1080ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
1081ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
1082ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1083ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param targetId The id of a target to ignore when running this transition.
1084ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
1085ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
1086ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1087ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1088ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(int targetId, boolean exclude) {
108930da61d477bcb6cc7718f9516c444359352fe148George Mount        if (targetId >= 0) {
109030da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetIdExcludes = excludeObject(mTargetIdExcludes, targetId, exclude);
109130da61d477bcb6cc7718f9516c444359352fe148George Mount        }
109230da61d477bcb6cc7718f9516c444359352fe148George Mount        return this;
109330da61d477bcb6cc7718f9516c444359352fe148George Mount    }
109430da61d477bcb6cc7718f9516c444359352fe148George Mount
109530da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
10960a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Whether to add the given transitionName to the list of target transitionNames to exclude
10970a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * from this transition. The <code>exclude</code> parameter specifies whether the target
109830da61d477bcb6cc7718f9516c444359352fe148George Mount     * should be added to or removed from the excluded list.
109930da61d477bcb6cc7718f9516c444359352fe148George Mount     *
110030da61d477bcb6cc7718f9516c444359352fe148George Mount     * <p>Excluding targets is a general mechanism for allowing transitions to run on
110130da61d477bcb6cc7718f9516c444359352fe148George Mount     * a view hierarchy while skipping target views that should not be part of
110230da61d477bcb6cc7718f9516c444359352fe148George Mount     * the transition. For example, you may want to avoid animating children
110330da61d477bcb6cc7718f9516c444359352fe148George Mount     * of a specific ListView or Spinner. Views can be excluded by their
11040a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * id, their instance reference, their transitionName, or by the Class of that view
110530da61d477bcb6cc7718f9516c444359352fe148George Mount     * (eg, {@link Spinner}).</p>
110630da61d477bcb6cc7718f9516c444359352fe148George Mount     *
110730da61d477bcb6cc7718f9516c444359352fe148George Mount     * @see #excludeTarget(View, boolean)
110830da61d477bcb6cc7718f9516c444359352fe148George Mount     * @see #excludeTarget(int, boolean)
110930da61d477bcb6cc7718f9516c444359352fe148George Mount     * @see #excludeTarget(Class, boolean)
111030da61d477bcb6cc7718f9516c444359352fe148George Mount     *
11110a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @param targetName The name of a target to ignore when running this transition.
111230da61d477bcb6cc7718f9516c444359352fe148George Mount     * @param exclude Whether to add the target to or remove the target from the
111330da61d477bcb6cc7718f9516c444359352fe148George Mount     * current list of excluded targets.
111430da61d477bcb6cc7718f9516c444359352fe148George Mount     * @return This transition object.
111530da61d477bcb6cc7718f9516c444359352fe148George Mount     */
11160a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount    public Transition excludeTarget(String targetName, boolean exclude) {
11170a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount        mTargetNameExcludes = excludeObject(mTargetNameExcludes, targetName, exclude);
1118ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
1119ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1120ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1121ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1122ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the children of the given id to the list of targets to exclude
1123ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * from this transition. The <code>exclude</code> parameter specifies whether
1124ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the children of the target should be added to or removed from the excluded list.
1125ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Excluding children in this way provides a simple mechanism for excluding all
1126ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * children of specific targets, rather than individually excluding each
1127ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * child individually.
1128ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1129ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1130ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1131ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1132ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1133ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1134ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1135ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1136ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
1137ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
1138ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
1139ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1140ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param targetId The id of a target whose children should be ignored when running
1141ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * this transition.
1142ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
1143ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded-child targets.
1144ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1145ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1146ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(int targetId, boolean exclude) {
114730da61d477bcb6cc7718f9516c444359352fe148George Mount        if (targetId >= 0) {
114830da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetIdChildExcludes = excludeObject(mTargetIdChildExcludes, targetId, exclude);
1149ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
115030da61d477bcb6cc7718f9516c444359352fe148George Mount        return this;
1151ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1152ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1153ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1154ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given target to the list of targets to exclude from this
1155ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
1156ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should be added to or removed from the excluded list.
1157ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1158ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1159ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1160ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1161ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1162ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1163ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1164ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1165ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
1166ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
1167ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
1168ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1169ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param target The target to ignore when running this transition.
1170ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
1171ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
1172ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1173ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1174ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(View target, boolean exclude) {
117530da61d477bcb6cc7718f9516c444359352fe148George Mount        mTargetExcludes = excludeObject(mTargetExcludes, target, exclude);
1176ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
1177ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1178ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1179ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1180ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the children of given target to the list of target children
1181ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * to exclude from this transition. The <code>exclude</code> parameter specifies
1182ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * whether the target should be added to or removed from the excluded list.
1183ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1184ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1185ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1186ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1187ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1188ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1189ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1190ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1191ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
1192ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
1193ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
1194ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1195ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param target The target to ignore when running this transition.
1196ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target to or remove the target from the
1197ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded targets.
1198ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1199ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1200ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(View target, boolean exclude) {
120130da61d477bcb6cc7718f9516c444359352fe148George Mount        mTargetChildExcludes = excludeObject(mTargetChildExcludes, target, exclude);
1202ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
1203ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1204ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1205ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1206ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility method to manage the boilerplate code that is the same whether we
1207ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * are excluding targets or their children.
1208ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
120930da61d477bcb6cc7718f9516c444359352fe148George Mount    private static <T> ArrayList<T> excludeObject(ArrayList<T> list, T target, boolean exclude) {
1210ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (target != null) {
1211ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (exclude) {
1212ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.add(list, target);
1213ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            } else {
1214ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = ArrayListManager.remove(list, target);
1215ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1216ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1217ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return list;
1218ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1219ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1220ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1221ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given type to the list of types to exclude from this
1222ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * transition. The <code>exclude</code> parameter specifies whether the target
1223ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * type should be added to or removed from the excluded list.
1224ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1225ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1226ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1227ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1228ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1229ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1230ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1231ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1232ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(Class, boolean)
1233ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(int, boolean)
1234ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(View, boolean)
1235ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1236ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param type The type to ignore when running this transition.
1237ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target type to or remove it from the
1238ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded target types.
1239ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1240ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1241ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeTarget(Class type, boolean exclude) {
124230da61d477bcb6cc7718f9516c444359352fe148George Mount        mTargetTypeExcludes = excludeObject(mTargetTypeExcludes, type, exclude);
1243ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
1244ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1245ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1246ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1247ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Whether to add the given type to the list of types whose children should
1248ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * be excluded from this transition. The <code>exclude</code> parameter
1249ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * specifies whether the target type should be added to or removed from
1250ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the excluded list.
1251ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1252ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1253ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * a view hierarchy while skipping target views that should not be part of
1254ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * the transition. For example, you may want to avoid animating children
1255ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * of a specific ListView or Spinner. Views can be excluded either by their
1256ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * id, or by their instance reference, or by the Class of that view
1257ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * (eg, {@link Spinner}).</p>
1258ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1259ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeTarget(Class, boolean)
1260ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(int, boolean)
1261ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #excludeChildren(View, boolean)
1262ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     *
1263ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param type The type to ignore when running this transition.
1264ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @param exclude Whether to add the target type to or remove it from the
1265ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * current list of excluded target types.
1266ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @return This transition object.
1267ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
1268ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    public Transition excludeChildren(Class type, boolean exclude) {
126930da61d477bcb6cc7718f9516c444359352fe148George Mount        mTargetTypeChildExcludes = excludeObject(mTargetTypeChildExcludes, type, exclude);
1270ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        return this;
1271ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
1272ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
1273ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
1274faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Sets the target view instances that this Transition is interested in
1275faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * animating. By default, there are no targets, and a Transition will
1276faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listen for changes on every view in the hierarchy below the sceneRoot
1277faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * of the Scene being transitioned into. Setting targets constrains
1278faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * the Transition to only listen for, and act on, these views.
1279faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * All other views will be ignored.
1280faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1281ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * <p>The target list is like the {@link #addTarget(int) targetId}
1282faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * list except this list specifies the actual View instances, not the ids
1283faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * of the views. This is an important distinction when scene changes involve
1284faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * view hierarchies which have been inflated separately; different views may
1285faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * share the same id but not actually be the same instance. If the transition
1286ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * should treat those views as the same, then {@link #addTarget(int)} should be used
1287d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * instead of {@link #addTarget(View)}. If, on the other hand, scene changes involve
1288faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * changes all within the same view hierarchy, among views which do not
1289d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * necessarily have ids set on them, then the target list of views may be more
1290faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * convenient.</p>
1291faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1292ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * @see #addTarget(int)
1293d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param target A View on which the Transition will act, must be non-null.
1294d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return The Transition to which the target is added.
1295d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Returning the same object makes it easier to chain calls during
1296d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * construction, such as
1297d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).addTarget(someView);</code>
1298d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     */
1299d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition addTarget(View target) {
1300d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        mTargets.add(target);
1301d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
1302d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
1303d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
1304d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    /**
1305d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Removes the given target from the list of targets that this Transition
1306d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * is interested in animating.
1307d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
1308d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param target The target view, must be non-null.
1309d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return Transition The Transition from which the target is removed.
1310faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Returning the same object makes it easier to chain calls during
1311faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * construction, such as
1312d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * <code>transitionSet.addTransitions(new Fade()).removeTarget(someView);</code>
1313faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1314d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition removeTarget(View target) {
1315d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (target != null) {
1316d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            mTargets.remove(target);
1317d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        }
1318faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return this;
1319faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1320faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1321faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
132230da61d477bcb6cc7718f9516c444359352fe148George Mount     * Removes the given target from the list of targets that this Transition
132330da61d477bcb6cc7718f9516c444359352fe148George Mount     * is interested in animating.
132430da61d477bcb6cc7718f9516c444359352fe148George Mount     *
132530da61d477bcb6cc7718f9516c444359352fe148George Mount     * @param target The type of the target view, must be non-null.
132630da61d477bcb6cc7718f9516c444359352fe148George Mount     * @return Transition The Transition from which the target is removed.
132730da61d477bcb6cc7718f9516c444359352fe148George Mount     * Returning the same object makes it easier to chain calls during
132830da61d477bcb6cc7718f9516c444359352fe148George Mount     * construction, such as
132930da61d477bcb6cc7718f9516c444359352fe148George Mount     * <code>transitionSet.addTransitions(new Fade()).removeTarget(someType);</code>
133030da61d477bcb6cc7718f9516c444359352fe148George Mount     */
133130da61d477bcb6cc7718f9516c444359352fe148George Mount    public Transition removeTarget(Class target) {
133230da61d477bcb6cc7718f9516c444359352fe148George Mount        if (target != null) {
133330da61d477bcb6cc7718f9516c444359352fe148George Mount            mTargetTypes.remove(target);
133430da61d477bcb6cc7718f9516c444359352fe148George Mount        }
133530da61d477bcb6cc7718f9516c444359352fe148George Mount        return this;
133630da61d477bcb6cc7718f9516c444359352fe148George Mount    }
133730da61d477bcb6cc7718f9516c444359352fe148George Mount
133830da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
133930da61d477bcb6cc7718f9516c444359352fe148George Mount     * Returns the list of target IDs that this transition limits itself to
134030da61d477bcb6cc7718f9516c444359352fe148George Mount     * tracking and animating. If the list is null or empty for
13410a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
134230da61d477bcb6cc7718f9516c444359352fe148George Mount     * {@link #getTargetTypes()} then this transition is
1343faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * not limited to specific views, and will handle changes to any views
1344faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * in the hierarchy of a scene change.
1345faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1346faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @return the list of target IDs
1347faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1348d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public List<Integer> getTargetIds() {
1349faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mTargetIds;
1350faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1351faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1352faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
135330da61d477bcb6cc7718f9516c444359352fe148George Mount     * Returns the list of target views that this transition limits itself to
135430da61d477bcb6cc7718f9516c444359352fe148George Mount     * tracking and animating. If the list is null or empty for
13550a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
135630da61d477bcb6cc7718f9516c444359352fe148George Mount     * {@link #getTargetTypes()} then this transition is
1357faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * not limited to specific views, and will handle changes to any views
1358faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * in the hierarchy of a scene change.
1359faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1360faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @return the list of target views
1361faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1362d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public List<View> getTargets() {
1363faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return mTargets;
1364faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1365faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1366faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
13670a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Returns the list of target transitionNames that this transition limits itself to
136830da61d477bcb6cc7718f9516c444359352fe148George Mount     * tracking and animating. If the list is null or empty for
13690a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
137030da61d477bcb6cc7718f9516c444359352fe148George Mount     * {@link #getTargetTypes()} then this transition is
137130da61d477bcb6cc7718f9516c444359352fe148George Mount     * not limited to specific views, and will handle changes to any views
137230da61d477bcb6cc7718f9516c444359352fe148George Mount     * in the hierarchy of a scene change.
137330da61d477bcb6cc7718f9516c444359352fe148George Mount     *
13740a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @return the list of target transitionNames
13750a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     */
13760a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount    public List<String> getTargetNames() {
13770a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount        return mTargetNames;
13780a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount    }
13790a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount
13800a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount    /**
13810a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * To be removed before L release.
13820a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * @hide
138330da61d477bcb6cc7718f9516c444359352fe148George Mount     */
138430da61d477bcb6cc7718f9516c444359352fe148George Mount    public List<String> getTargetViewNames() {
138530da61d477bcb6cc7718f9516c444359352fe148George Mount        return mTargetNames;
138630da61d477bcb6cc7718f9516c444359352fe148George Mount    }
138730da61d477bcb6cc7718f9516c444359352fe148George Mount
138830da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
13890a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * Returns the list of target transitionNames that this transition limits itself to
139030da61d477bcb6cc7718f9516c444359352fe148George Mount     * tracking and animating. If the list is null or empty for
13910a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
139230da61d477bcb6cc7718f9516c444359352fe148George Mount     * {@link #getTargetTypes()} then this transition is
139330da61d477bcb6cc7718f9516c444359352fe148George Mount     * not limited to specific views, and will handle changes to any views
139430da61d477bcb6cc7718f9516c444359352fe148George Mount     * in the hierarchy of a scene change.
139530da61d477bcb6cc7718f9516c444359352fe148George Mount     *
139630da61d477bcb6cc7718f9516c444359352fe148George Mount     * @return the list of target Types
139730da61d477bcb6cc7718f9516c444359352fe148George Mount     */
139830da61d477bcb6cc7718f9516c444359352fe148George Mount    public List<Class> getTargetTypes() {
139930da61d477bcb6cc7718f9516c444359352fe148George Mount        return mTargetTypes;
140030da61d477bcb6cc7718f9516c444359352fe148George Mount    }
140130da61d477bcb6cc7718f9516c444359352fe148George Mount
140230da61d477bcb6cc7718f9516c444359352fe148George Mount    /**
1403faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Recursive method that captures values for the given view and the
1404faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * hierarchy underneath it.
1405faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param sceneRoot The root of the view hierarchy being captured
1406faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param start true if this capture is happening before the scene change,
1407faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * false otherwise
1408faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1409faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    void captureValues(ViewGroup sceneRoot, boolean start) {
1410df32aa87150768795816852c6393306893467ecaChet Haase        clearValues(start);
141130da61d477bcb6cc7718f9516c444359352fe148George Mount        if ((mTargetIds.size() > 0 || mTargets.size() > 0)
141230da61d477bcb6cc7718f9516c444359352fe148George Mount                && (mTargetNames == null || mTargetNames.isEmpty())
141330da61d477bcb6cc7718f9516c444359352fe148George Mount                && (mTargetTypes == null || mTargetTypes.isEmpty())) {
141430da61d477bcb6cc7718f9516c444359352fe148George Mount            for (int i = 0; i < mTargetIds.size(); ++i) {
141530da61d477bcb6cc7718f9516c444359352fe148George Mount                int id = mTargetIds.get(i);
141630da61d477bcb6cc7718f9516c444359352fe148George Mount                View view = sceneRoot.findViewById(id);
141730da61d477bcb6cc7718f9516c444359352fe148George Mount                if (view != null) {
141830da61d477bcb6cc7718f9516c444359352fe148George Mount                    TransitionValues values = new TransitionValues();
141930da61d477bcb6cc7718f9516c444359352fe148George Mount                    values.view = view;
142030da61d477bcb6cc7718f9516c444359352fe148George Mount                    if (start) {
142130da61d477bcb6cc7718f9516c444359352fe148George Mount                        captureStartValues(values);
142230da61d477bcb6cc7718f9516c444359352fe148George Mount                    } else {
142330da61d477bcb6cc7718f9516c444359352fe148George Mount                        captureEndValues(values);
142430da61d477bcb6cc7718f9516c444359352fe148George Mount                    }
14255030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                    values.targetedTransitions.add(this);
142630da61d477bcb6cc7718f9516c444359352fe148George Mount                    capturePropagationValues(values);
142730da61d477bcb6cc7718f9516c444359352fe148George Mount                    if (start) {
14285030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                        addViewValues(mStartValues, view, values);
142930da61d477bcb6cc7718f9516c444359352fe148George Mount                    } else {
14305030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                        addViewValues(mEndValues, view, values);
1431faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
1432faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1433faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
143430da61d477bcb6cc7718f9516c444359352fe148George Mount            for (int i = 0; i < mTargets.size(); ++i) {
143530da61d477bcb6cc7718f9516c444359352fe148George Mount                View view = mTargets.get(i);
143630da61d477bcb6cc7718f9516c444359352fe148George Mount                TransitionValues values = new TransitionValues();
143730da61d477bcb6cc7718f9516c444359352fe148George Mount                values.view = view;
143830da61d477bcb6cc7718f9516c444359352fe148George Mount                if (start) {
143930da61d477bcb6cc7718f9516c444359352fe148George Mount                    captureStartValues(values);
144030da61d477bcb6cc7718f9516c444359352fe148George Mount                } else {
144130da61d477bcb6cc7718f9516c444359352fe148George Mount                    captureEndValues(values);
144230da61d477bcb6cc7718f9516c444359352fe148George Mount                }
14435030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                values.targetedTransitions.add(this);
144430da61d477bcb6cc7718f9516c444359352fe148George Mount                capturePropagationValues(values);
144530da61d477bcb6cc7718f9516c444359352fe148George Mount                if (start) {
14462deeaa33143362846299bb424b3b1a52ca45deebGeorge Mount                    addViewValues(mStartValues, view, values);
144730da61d477bcb6cc7718f9516c444359352fe148George Mount                } else {
14482deeaa33143362846299bb424b3b1a52ca45deebGeorge Mount                    addViewValues(mEndValues, view, values);
1449faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1450faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1451faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1452faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            captureHierarchy(sceneRoot, start);
1453faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1454d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        if (!start && mNameOverrides != null) {
1455d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            int numOverrides = mNameOverrides.size();
1456d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            ArrayList<View> overriddenViews = new ArrayList<View>(numOverrides);
1457d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            for (int i = 0; i < numOverrides; i++) {
1458d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                String fromName = mNameOverrides.keyAt(i);
1459d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                overriddenViews.add(mStartValues.nameValues.remove(fromName));
1460d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            }
1461d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            for (int i = 0; i < numOverrides; i++) {
1462d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                View view = overriddenViews.get(i);
1463d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                if (view != null) {
1464d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                    String toName = mNameOverrides.valueAt(i);
1465d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                    mStartValues.nameValues.put(toName, view);
1466d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                }
1467d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            }
1468d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        }
1469faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1470faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
147130da61d477bcb6cc7718f9516c444359352fe148George Mount    static void addViewValues(TransitionValuesMaps transitionValuesMaps,
14725030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            View view, TransitionValues transitionValues) {
147330da61d477bcb6cc7718f9516c444359352fe148George Mount        transitionValuesMaps.viewValues.put(view, transitionValues);
147430da61d477bcb6cc7718f9516c444359352fe148George Mount        int id = view.getId();
147530da61d477bcb6cc7718f9516c444359352fe148George Mount        if (id >= 0) {
147630da61d477bcb6cc7718f9516c444359352fe148George Mount            if (transitionValuesMaps.idValues.indexOfKey(id) >= 0) {
147730da61d477bcb6cc7718f9516c444359352fe148George Mount                // Duplicate IDs cannot match by ID.
147830da61d477bcb6cc7718f9516c444359352fe148George Mount                transitionValuesMaps.idValues.put(id, null);
147930da61d477bcb6cc7718f9516c444359352fe148George Mount            } else {
148030da61d477bcb6cc7718f9516c444359352fe148George Mount                transitionValuesMaps.idValues.put(id, view);
148130da61d477bcb6cc7718f9516c444359352fe148George Mount            }
148230da61d477bcb6cc7718f9516c444359352fe148George Mount        }
14830a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount        String name = view.getTransitionName();
148430da61d477bcb6cc7718f9516c444359352fe148George Mount        if (name != null) {
148530da61d477bcb6cc7718f9516c444359352fe148George Mount            if (transitionValuesMaps.nameValues.containsKey(name)) {
14860a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount                // Duplicate transitionNames: cannot match by transitionName.
148730da61d477bcb6cc7718f9516c444359352fe148George Mount                transitionValuesMaps.nameValues.put(name, null);
148830da61d477bcb6cc7718f9516c444359352fe148George Mount            } else {
148930da61d477bcb6cc7718f9516c444359352fe148George Mount                transitionValuesMaps.nameValues.put(name, view);
149030da61d477bcb6cc7718f9516c444359352fe148George Mount            }
149130da61d477bcb6cc7718f9516c444359352fe148George Mount        }
149230da61d477bcb6cc7718f9516c444359352fe148George Mount        if (view.getParent() instanceof ListView) {
149330da61d477bcb6cc7718f9516c444359352fe148George Mount            ListView listview = (ListView) view.getParent();
149430da61d477bcb6cc7718f9516c444359352fe148George Mount            if (listview.getAdapter().hasStableIds()) {
149530da61d477bcb6cc7718f9516c444359352fe148George Mount                int position = listview.getPositionForView(view);
149630da61d477bcb6cc7718f9516c444359352fe148George Mount                long itemId = listview.getItemIdAtPosition(position);
149730da61d477bcb6cc7718f9516c444359352fe148George Mount                if (transitionValuesMaps.itemIdValues.indexOfKey(itemId) >= 0) {
149830da61d477bcb6cc7718f9516c444359352fe148George Mount                    // Duplicate item IDs: cannot match by item ID.
149930da61d477bcb6cc7718f9516c444359352fe148George Mount                    View alreadyMatched = transitionValuesMaps.itemIdValues.get(itemId);
150030da61d477bcb6cc7718f9516c444359352fe148George Mount                    if (alreadyMatched != null) {
15015030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                        alreadyMatched.setHasTransientState(false);
150230da61d477bcb6cc7718f9516c444359352fe148George Mount                        transitionValuesMaps.itemIdValues.put(itemId, null);
150330da61d477bcb6cc7718f9516c444359352fe148George Mount                    }
150430da61d477bcb6cc7718f9516c444359352fe148George Mount                } else {
15055030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                    view.setHasTransientState(true);
150630da61d477bcb6cc7718f9516c444359352fe148George Mount                    transitionValuesMaps.itemIdValues.put(itemId, view);
150730da61d477bcb6cc7718f9516c444359352fe148George Mount                }
150830da61d477bcb6cc7718f9516c444359352fe148George Mount            }
150930da61d477bcb6cc7718f9516c444359352fe148George Mount        }
151030da61d477bcb6cc7718f9516c444359352fe148George Mount    }
151130da61d477bcb6cc7718f9516c444359352fe148George Mount
1512faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1513df32aa87150768795816852c6393306893467ecaChet Haase     * Clear valuesMaps for specified start/end state
1514df32aa87150768795816852c6393306893467ecaChet Haase     *
1515df32aa87150768795816852c6393306893467ecaChet Haase     * @param start true if the start values should be cleared, false otherwise
1516df32aa87150768795816852c6393306893467ecaChet Haase     */
1517df32aa87150768795816852c6393306893467ecaChet Haase    void clearValues(boolean start) {
1518df32aa87150768795816852c6393306893467ecaChet Haase        if (start) {
1519df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.viewValues.clear();
1520df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.idValues.clear();
1521df32aa87150768795816852c6393306893467ecaChet Haase            mStartValues.itemIdValues.clear();
1522d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            mStartValues.nameValues.clear();
15234d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            mStartValuesList = null;
1524df32aa87150768795816852c6393306893467ecaChet Haase        } else {
1525df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.viewValues.clear();
1526df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.idValues.clear();
1527df32aa87150768795816852c6393306893467ecaChet Haase            mEndValues.itemIdValues.clear();
1528d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount            mEndValues.nameValues.clear();
15294d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            mEndValuesList = null;
1530df32aa87150768795816852c6393306893467ecaChet Haase        }
1531df32aa87150768795816852c6393306893467ecaChet Haase    }
1532df32aa87150768795816852c6393306893467ecaChet Haase
1533df32aa87150768795816852c6393306893467ecaChet Haase    /**
1534faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Recursive method which captures values for an entire view hierarchy,
1535faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * starting at some root view. Transitions without targetIDs will use this
1536faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * method to capture values for all possible views.
1537faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1538faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param view The view for which to capture values. Children of this View
1539faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * will also be captured, recursively down to the leaf nodes.
1540faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param start true if values are being captured in the start scene, false
1541faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * otherwise.
1542faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1543faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    private void captureHierarchy(View view, boolean start) {
1544faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (view == null) {
1545faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            return;
1546faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
154730da61d477bcb6cc7718f9516c444359352fe148George Mount        int id = view.getId();
1548ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetIdExcludes != null && mTargetIdExcludes.contains(id)) {
1549ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return;
1550ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1551ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetExcludes != null && mTargetExcludes.contains(view)) {
1552ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return;
1553ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1554ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        if (mTargetTypeExcludes != null && view != null) {
1555ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            int numTypes = mTargetTypeExcludes.size();
1556ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            for (int i = 0; i < numTypes; ++i) {
1557ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (mTargetTypeExcludes.get(i).isInstance(view)) {
1558ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    return;
1559ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
1560ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1561ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
1562e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount        if (view.getParent() instanceof ViewGroup) {
1563e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            TransitionValues values = new TransitionValues();
1564e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            values.view = view;
1565e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            if (start) {
1566e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                captureStartValues(values);
1567faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
1568e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount                captureEndValues(values);
1569faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
15705030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            values.targetedTransitions.add(this);
1571d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            capturePropagationValues(values);
1572e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount            if (start) {
15735030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                addViewValues(mStartValues, view, values);
1574faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
15755030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                addViewValues(mEndValues, view, values);
1576faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1577faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1578faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (view instanceof ViewGroup) {
1579ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            // Don't traverse child hierarchy if there are any child-excludes on this view
1580ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (mTargetIdChildExcludes != null && mTargetIdChildExcludes.contains(id)) {
1581ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                return;
1582ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1583ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (mTargetChildExcludes != null && mTargetChildExcludes.contains(view)) {
1584ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                return;
1585ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
158630da61d477bcb6cc7718f9516c444359352fe148George Mount            if (mTargetTypeChildExcludes != null) {
1587ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                int numTypes = mTargetTypeChildExcludes.size();
1588ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                for (int i = 0; i < numTypes; ++i) {
1589ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    if (mTargetTypeChildExcludes.get(i).isInstance(view)) {
1590ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                        return;
1591ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    }
1592ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
1593ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
1594faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            ViewGroup parent = (ViewGroup) view;
1595faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            for (int i = 0; i < parent.getChildCount(); ++i) {
1596faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                captureHierarchy(parent.getChildAt(i), start);
1597faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1598faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1599faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1600faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1601faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
16026ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * This method can be called by transitions to get the TransitionValues for
16036ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * any particular view during the transition-playing process. This might be
16046ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * necessary, for example, to query the before/after state of related views
16056ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     * for a given transition.
16066ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     */
1607d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public TransitionValues getTransitionValues(View view, boolean start) {
16086ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        if (mParent != null) {
16096ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            return mParent.getTransitionValues(view, start);
16106ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        }
16116ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        TransitionValuesMaps valuesMaps = start ? mStartValues : mEndValues;
161230da61d477bcb6cc7718f9516c444359352fe148George Mount        return valuesMaps.viewValues.get(view);
16136ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
16146ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
16156ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    /**
16164d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * Find the matched start or end value for a given View. This is only valid
16174d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * after playTransition starts. For example, it will be valid in
16184d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}, but not
16194d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * in {@link #captureStartValues(TransitionValues)}.
16204d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     *
16214d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * @param view The view to find the match for.
16224d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * @param viewInStart Is View from the start values or end values.
16234d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * @return The matching TransitionValues for view in either start or end values, depending
16244d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     * on viewInStart or null if there is no match for the given view.
16254d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount     */
16264d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    TransitionValues getMatchedTransitionValues(View view, boolean viewInStart) {
16274d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        if (mParent != null) {
16284d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            return mParent.getMatchedTransitionValues(view, viewInStart);
16294d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        }
16304d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        ArrayList<TransitionValues> lookIn = viewInStart ? mStartValuesList : mEndValuesList;
16314d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        if (lookIn == null) {
16324d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            return null;
16334d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        }
16344d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        int count = lookIn.size();
16354d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        int index = -1;
16364d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        for (int i = 0; i < count; i++) {
16374d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            TransitionValues values = lookIn.get(i);
16384d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            if (values == null) {
16394d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                return null;
16404d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            }
16414d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            if (values.view == view) {
16424d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                index = i;
16434d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount                break;
16444d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            }
16454d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        }
16464d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        TransitionValues values = null;
16474d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        if (index >= 0) {
16484d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            ArrayList<TransitionValues> matchIn = viewInStart ? mEndValuesList : mStartValuesList;
16494d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            values = matchIn.get(index);
16504d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        }
16514d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        return values;
16524d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    }
16534d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount
16544d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount    /**
1655199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Pauses this transition, sending out calls to {@link
1656199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * TransitionListener#onTransitionPause(Transition)} to all listeners
1657199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * and pausing all running animators started by this transition.
1658199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1659199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @hide
1660199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
1661cf68aad3164303df59b2a669d186a94533c9c743George Mount    public void pause(View sceneRoot) {
1662a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase        if (!mEnded) {
1663a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1664a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            int numOldAnims = runningAnimators.size();
166551c014843a6d339d115dfa88b9ee2fff90a8b844George Mount            if (sceneRoot != null) {
166651c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                WindowId windowId = sceneRoot.getWindowId();
166751c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                for (int i = numOldAnims - 1; i >= 0; i--) {
166851c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                    AnimationInfo info = runningAnimators.valueAt(i);
16696276cd4b8defba1b6fef47ebc1bbe14498655b94George Mount                    if (info.view != null && windowId != null && windowId.equals(info.windowId)) {
167051c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                        Animator anim = runningAnimators.keyAt(i);
167151c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                        anim.pause();
167251c014843a6d339d115dfa88b9ee2fff90a8b844George Mount                    }
1673cf68aad3164303df59b2a669d186a94533c9c743George Mount                }
1674a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            }
1675a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1676a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                ArrayList<TransitionListener> tmpListeners =
1677a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1678a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                int numListeners = tmpListeners.size();
1679a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                for (int i = 0; i < numListeners; ++i) {
1680a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    tmpListeners.get(i).onTransitionPause(this);
1681a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                }
1682199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1683a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mPaused = true;
1684199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1685199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1686199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1687199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1688199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Resumes this transition, sending out calls to {@link
1689199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * TransitionListener#onTransitionPause(Transition)} to all listeners
1690199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * and pausing all running animators started by this transition.
1691199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
1692199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @hide
1693199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
1694cf68aad3164303df59b2a669d186a94533c9c743George Mount    public void resume(View sceneRoot) {
1695199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (mPaused) {
1696a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            if (!mEnded) {
1697a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1698a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                int numOldAnims = runningAnimators.size();
1699cf68aad3164303df59b2a669d186a94533c9c743George Mount                WindowId windowId = sceneRoot.getWindowId();
1700a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                for (int i = numOldAnims - 1; i >= 0; i--) {
1701cf68aad3164303df59b2a669d186a94533c9c743George Mount                    AnimationInfo info = runningAnimators.valueAt(i);
17026276cd4b8defba1b6fef47ebc1bbe14498655b94George Mount                    if (info.view != null && windowId != null && windowId.equals(info.windowId)) {
1703cf68aad3164303df59b2a669d186a94533c9c743George Mount                        Animator anim = runningAnimators.keyAt(i);
1704cf68aad3164303df59b2a669d186a94533c9c743George Mount                        anim.resume();
1705cf68aad3164303df59b2a669d186a94533c9c743George Mount                    }
1706a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                }
1707a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                if (mListeners != null && mListeners.size() > 0) {
1708a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    ArrayList<TransitionListener> tmpListeners =
1709a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                            (ArrayList<TransitionListener>) mListeners.clone();
1710a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    int numListeners = tmpListeners.size();
1711a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    for (int i = 0; i < numListeners; ++i) {
1712a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                        tmpListeners.get(i).onTransitionResume(this);
1713a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase                    }
1714199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                }
1715199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1716199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            mPaused = false;
1717199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1718199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
1719199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1720199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
1721faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Called by TransitionManager to play the transition. This calls
1722d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * createAnimators() to set things up and create all of the animations and then
17232ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase     * runAnimations() to actually start the animations.
1724faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
17256ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    void playTransition(ViewGroup sceneRoot) {
17264d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        mStartValuesList = new ArrayList<TransitionValues>();
17274d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        mEndValuesList = new ArrayList<TransitionValues>();
17284d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        matchStartAndEnd(mStartValues, mEndValues);
17294d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount
1730199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
1731199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        int numOldAnims = runningAnimators.size();
1732fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        WindowId windowId = sceneRoot.getWindowId();
1733199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        for (int i = numOldAnims - 1; i >= 0; i--) {
1734199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            Animator anim = runningAnimators.keyAt(i);
1735199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            if (anim != null) {
1736199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                AnimationInfo oldInfo = runningAnimators.get(anim);
1737fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                if (oldInfo != null && oldInfo.view != null && oldInfo.windowId == windowId) {
1738199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    TransitionValues oldValues = oldInfo.values;
1739199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    View oldView = oldInfo.view;
17405030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                    TransitionValues startValues = getTransitionValues(oldView, true);
17415030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                    TransitionValues endValues = getMatchedTransitionValues(oldView, true);
17425030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                    boolean cancel = (startValues != null || endValues != null) &&
17435030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount                            oldInfo.transition.areValuesChanged(oldValues, endValues);
1744199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    if (cancel) {
1745199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        if (anim.isRunning() || anim.isStarted()) {
1746199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            if (DBG) {
1747199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                Log.d(LOG_TAG, "Canceling anim " + anim);
1748199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
1749199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            anim.cancel();
1750199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        } else {
1751199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            if (DBG) {
1752199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                                Log.d(LOG_TAG, "removing anim from info list: " + anim);
1753199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            }
1754199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                            runningAnimators.remove(anim);
1755199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                        }
1756199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    }
1757199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                }
1758199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            }
1759199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
1760199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
17614d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount        createAnimators(sceneRoot, mStartValues, mEndValues, mStartValuesList, mEndValuesList);
1762d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        runAnimators();
1763faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1764faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
17654c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount    boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
17664c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        boolean valuesChanged = false;
17674c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        // if oldValues null, then transition didn't care to stash values,
17684c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        // and won't get canceled
17694c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        if (oldValues != null && newValues != null) {
1770c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu            String[] properties = getTransitionProperties();
1771c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu            if (properties != null) {
1772c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                int count = properties.length;
1773c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                for (int i = 0; i < count; i++) {
1774c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                    if (isValueChanged(oldValues, newValues, properties[i])) {
1775c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                        valuesChanged = true;
1776c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                        break;
1777c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                    }
1778c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                }
1779c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu            } else {
1780c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                for (String key : oldValues.values.keySet()) {
1781c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                    if (isValueChanged(oldValues, newValues, key)) {
1782c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                        valuesChanged = true;
1783c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                        break;
17844c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount                    }
17854c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount                }
17864c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount            }
17874c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        }
17884c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        return valuesChanged;
17894c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount    }
17904c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount
1791c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu    private static boolean isValueChanged(TransitionValues oldValues, TransitionValues newValues,
1792c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu            String key) {
1793cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount        if (oldValues.values.containsKey(key) != newValues.values.containsKey(key)) {
1794cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount            // The transition didn't care about this particular value, so we don't care, either.
1795cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount            return false;
1796cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount        }
1797c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu        Object oldValue = oldValues.values.get(key);
1798c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu        Object newValue = newValues.values.get(key);
17995030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount        boolean changed;
18005030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount        if (oldValue == null && newValue == null) {
18015030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            // both are null
18025030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            changed = false;
18035030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount        } else if (oldValue == null || newValue == null) {
18045030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            // one is null
18055030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            changed = true;
18065030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount        } else {
18075030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            // neither is null
18085030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount            changed = !oldValue.equals(newValue);
18095030c7f6f15c5c2cac2403f863e4f618a8cfaedfGeorge Mount        }
1810c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu        if (DBG && changed) {
1811c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu            Log.d(LOG_TAG, "Transition.playTransition: " +
1812c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                    "oldValue != newValue for " + key +
1813c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu                    ": old, new = " + oldValue + ", " + newValue);
1814c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu        }
1815c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu        return changed;
1816c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu    }
1817c94e2b393f6eba684ee2c84eaa50746fc1459d0fDake Gu
1818faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1819faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This is a utility method used by subclasses to handle standard parts of
1820faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * setting up and running an Animator: it sets the {@link #getDuration()
1821faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * duration} and the {@link #getStartDelay() startDelay}, starts the
1822199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animation, and, when the animator ends, calls {@link #end()}.
1823faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1824faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param animator The Animator to be run during this transition.
1825faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1826faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1827faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1828faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    protected void animate(Animator animator) {
1829faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        // TODO: maybe pass auto-end as a boolean parameter?
1830faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (animator == null) {
1831199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            end();
1832faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1833faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getDuration() >= 0) {
1834faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                animator.setDuration(getDuration());
1835faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1836faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getStartDelay() >= 0) {
1837d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                animator.setStartDelay(getStartDelay() + animator.getStartDelay());
1838faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1839faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (getInterpolator() != null) {
1840faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                animator.setInterpolator(getInterpolator());
1841faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1842faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            animator.addListener(new AnimatorListenerAdapter() {
1843faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                @Override
1844faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                public void onAnimationEnd(Animator animation) {
1845199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase                    end();
1846faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    animation.removeListener(this);
1847faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1848faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            });
1849faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            animator.start();
1850faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1851faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1852faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1853faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1854faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method is called automatically by the transition and
1855d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * TransitionSet classes prior to a Transition subclass starting;
1856faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * subclasses should not need to call it directly.
1857faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1858faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1859faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1860199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void start() {
1861faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mNumInstances == 0) {
1862faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1863faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                ArrayList<TransitionListener> tmpListeners =
1864faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1865faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                int numListeners = tmpListeners.size();
1866faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                for (int i = 0; i < numListeners; ++i) {
1867faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    tmpListeners.get(i).onTransitionStart(this);
1868faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1869faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1870a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mEnded = false;
1871faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1872faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mNumInstances++;
1873faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1874faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1875faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1876faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method is called automatically by the Transition and
1877d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * TransitionSet classes when a transition finishes, either because
1878faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * a transition did nothing (returned a null Animator from
1879d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * {@link Transition#createAnimator(ViewGroup, TransitionValues,
1880faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * TransitionValues)}) or because the transition returned a valid
1881199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Animator and end() was called in the onAnimationEnd()
1882faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * callback of the AnimatorListener.
1883faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1884faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
1885faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1886199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void end() {
1887faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        --mNumInstances;
1888faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mNumInstances == 0) {
1889faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            if (mListeners != null && mListeners.size() > 0) {
1890faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                ArrayList<TransitionListener> tmpListeners =
1891faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                        (ArrayList<TransitionListener>) mListeners.clone();
1892faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                int numListeners = tmpListeners.size();
1893faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                for (int i = 0; i < numListeners; ++i) {
1894faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    tmpListeners.get(i).onTransitionEnd(this);
1895faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1896faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
18976ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            for (int i = 0; i < mStartValues.itemIdValues.size(); ++i) {
189830da61d477bcb6cc7718f9516c444359352fe148George Mount                View view = mStartValues.itemIdValues.valueAt(i);
189930da61d477bcb6cc7718f9516c444359352fe148George Mount                if (view != null) {
190030da61d477bcb6cc7718f9516c444359352fe148George Mount                    view.setHasTransientState(false);
1901faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1902faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
19036ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            for (int i = 0; i < mEndValues.itemIdValues.size(); ++i) {
190430da61d477bcb6cc7718f9516c444359352fe148George Mount                View view = mEndValues.itemIdValues.valueAt(i);
190530da61d477bcb6cc7718f9516c444359352fe148George Mount                if (view != null) {
190630da61d477bcb6cc7718f9516c444359352fe148George Mount                    view.setHasTransientState(false);
1907faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
1908faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1909a56205c485deb5a95c1e4f79ef2b09d14cbc9524Chet Haase            mEnded = true;
1910faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1911faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1912faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1913faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1914faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * This method cancels a transition that is currently running.
1915d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     *
1916d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @hide
1917faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1918199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    protected void cancel() {
1919e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        int numAnimators = mCurrentAnimators.size();
192025a738fb257aacfc87d3363a834ed6e0b050c3b1Chet Haase        for (int i = numAnimators - 1; i >= 0; i--) {
1921e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            Animator animator = mCurrentAnimators.get(i);
1922e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase            animator.cancel();
1923e9d32ea13ee14fc0eb4e45ca627ca77729d38bfeChet Haase        }
1924faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners != null && mListeners.size() > 0) {
1925faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            ArrayList<TransitionListener> tmpListeners =
1926faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    (ArrayList<TransitionListener>) mListeners.clone();
1927faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            int numListeners = tmpListeners.size();
1928faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            for (int i = 0; i < numListeners; ++i) {
1929faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                tmpListeners.get(i).onTransitionCancel(this);
1930faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
1931faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1932faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1933faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1934faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1935faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Adds a listener to the set of listeners that are sent events through the
1936faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * life of an animation, such as start, repeat, and end.
1937faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1938faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param listener the listener to be added to the current set of listeners
1939faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * for this animation.
1940d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
1941faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1942d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition addListener(TransitionListener listener) {
1943faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners == null) {
1944faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            mListeners = new ArrayList<TransitionListener>();
1945faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1946faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mListeners.add(listener);
1947d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
1948faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1949faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1950faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
1951faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Removes a listener from the set listening to this animation.
1952faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
1953faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @param listener the listener to be removed from the current set of
1954faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * listeners for this transition.
1955d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return This transition object.
1956faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
1957d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Transition removeListener(TransitionListener listener) {
1958faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners == null) {
1959d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            return this;
1960faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1961faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        mListeners.remove(listener);
1962faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (mListeners.size() == 0) {
1963faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            mListeners = null;
1964faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
1965d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
1966faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
1967faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
1968d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1969d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Sets the callback to use to find the epicenter of a Transition. A null value indicates
1970dc21d3b2804c24fe29ec860796d11185901364c4George Mount     * that there is no epicenter in the Transition and onGetEpicenter() will return null.
1971d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Transitions like {@link android.transition.Explode} use a point or Rect to orient
1972d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the direction of travel. This is called the epicenter of the Transition and is
1973d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * typically centered on a touched View. The
1974d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
1975d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * dynamically retrieve the epicenter during a Transition.
1976d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param epicenterCallback The callback to use to find the epicenter of the Transition.
1977d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1978d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public void setEpicenterCallback(EpicenterCallback epicenterCallback) {
1979d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        mEpicenterCallback = epicenterCallback;
1980d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1981d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1982d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1983d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Returns the callback used to find the epicenter of the Transition.
1984d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Transitions like {@link android.transition.Explode} use a point or Rect to orient
1985d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the direction of travel. This is called the epicenter of the Transition and is
1986d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * typically centered on a touched View. The
1987d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
1988d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * dynamically retrieve the epicenter during a Transition.
1989d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return the callback used to find the epicenter of the Transition.
1990d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
1991d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public EpicenterCallback getEpicenterCallback() {
1992d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        return mEpicenterCallback;
1993d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
1994d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
1995d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
1996d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Returns the epicenter as specified by the
1997d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
1998d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return the epicenter as specified by the
1999d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
2000d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @see #setEpicenterCallback(android.transition.Transition.EpicenterCallback)
2001d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
2002d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public Rect getEpicenter() {
2003d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (mEpicenterCallback == null) {
2004d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            return null;
2005d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
2006dc21d3b2804c24fe29ec860796d11185901364c4George Mount        return mEpicenterCallback.onGetEpicenter(this);
2007d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
2008d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
2009d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
2010ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * Sets the algorithm used to calculate two-dimensional interpolation.
2011ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * <p>
2012ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *     Transitions such as {@link android.transition.ChangeBounds} move Views, typically
2013ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *     in a straight path between the start and end positions. Applications that desire to
2014ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *     have these motions move in a curve can change how Views interpolate in two dimensions
2015ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *     by extending PathMotion and implementing
2016ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *     {@link android.transition.PathMotion#getPath(float, float, float, float)}.
2017ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * </p>
2018f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * <p>
2019f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *     When describing in XML, use a nested XML tag for the path motion. It can be one of
2020f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *     the built-in tags <code>arcMotion</code> or <code>patternPathMotion</code> or it can
2021f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *     be a custom PathMotion using <code>pathMotion</code> with the <code>class</code>
2022f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *     attributed with the fully-described class name. For example:</p>
2023f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * <pre>
2024f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * {@code
2025f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * &lt;changeBounds>
2026f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *     &lt;pathMotion class="my.app.transition.MyPathMotion"/>
2027f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * &lt;/changeBounds>
2028f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * }
2029f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * </pre>
2030f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * <p>or</p>
2031f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * <pre>
2032f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * {@code
2033f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * &lt;changeBounds>
2034f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *   &lt;arcMotion android:minimumHorizontalAngle="15"
2035f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *     android:minimumVerticalAngle="0" android:maximumAngle="90"/>
2036f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * &lt;/changeBounds>
2037f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * }
2038f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * </pre>
2039f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *
2040ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * @param pathMotion Algorithm object to use for determining how to interpolate in two
2041ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *                   dimensions. If null, a straight-path algorithm will be used.
2042f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * @see android.transition.ArcMotion
2043f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * @see PatternPathMotion
2044f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * @see android.transition.PathMotion
2045ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     */
2046ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    public void setPathMotion(PathMotion pathMotion) {
2047ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        if (pathMotion == null) {
2048ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            mPathMotion = STRAIGHT_PATH_MOTION;
2049ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        } else {
2050ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            mPathMotion = pathMotion;
2051ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        }
2052ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    }
2053ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
2054ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    /**
2055ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * Returns the algorithm object used to interpolate along two dimensions. This is typically
2056ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * used to determine the View motion between two points.
2057ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *
2058f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * <p>
2059f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *     When describing in XML, use a nested XML tag for the path motion. It can be one of
2060f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *     the built-in tags <code>arcMotion</code> or <code>patternPathMotion</code> or it can
2061f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *     be a custom PathMotion using <code>pathMotion</code> with the <code>class</code>
2062f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *     attributed with the fully-described class name. For example:</p>
2063f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * <pre>
2064f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * {@code
2065f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * &lt;changeBounds>
2066f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *     &lt;pathMotion class="my.app.transition.MyPathMotion"/>
2067f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * &lt;/changeBounds>}
2068f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * </pre>
2069f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * <p>or</p>
2070f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * <pre>
2071f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * {@code
2072f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * &lt;changeBounds>
2073f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *   &lt;arcMotion android:minimumHorizontalAngle="15"
2074f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *              android:minimumVerticalAngle="0"
2075f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *              android:maximumAngle="90"/>
2076f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * &lt;/changeBounds>}
2077f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * </pre>
2078f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     *
2079ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * @return The algorithm object used to interpolate along two dimensions.
2080f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * @see android.transition.ArcMotion
2081f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * @see PatternPathMotion
2082f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount     * @see android.transition.PathMotion
2083ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     */
2084ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    public PathMotion getPathMotion() {
2085ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        return mPathMotion;
2086ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    }
2087ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
2088ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    /**
2089d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Sets the method for determining Animator start delays.
2090d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * When a Transition affects several Views like {@link android.transition.Explode} or
2091d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
2092d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * such that the Animator start delay depends on position of the View. The
2093d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * TransitionPropagation specifies how the start delays are calculated.
2094d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param transitionPropagation The class used to determine the start delay of
2095d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *                              Animators created by this Transition. A null value
2096d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *                              indicates that no delay should be used.
2097d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
2098d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public void setPropagation(TransitionPropagation transitionPropagation) {
2099d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        mPropagation = transitionPropagation;
2100d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
2101d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
2102d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
2103d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Returns the {@link android.transition.TransitionPropagation} used to calculate Animator start
2104d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * delays.
2105d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * When a Transition affects several Views like {@link android.transition.Explode} or
2106d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
2107d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * such that the Animator start delay depends on position of the View. The
2108d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * TransitionPropagation specifies how the start delays are calculated.
2109d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return the {@link android.transition.TransitionPropagation} used to calculate Animator start
2110d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * delays. This is null by default.
2111d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
2112d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public TransitionPropagation getPropagation() {
2113d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        return mPropagation;
2114d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
2115d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
2116d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
2117d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Captures TransitionPropagation values for the given view and the
2118d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * hierarchy underneath it.
2119d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
2120d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    void capturePropagationValues(TransitionValues transitionValues) {
212131a217290cf376d0573fc36e21c8940987485019George Mount        if (mPropagation != null && !transitionValues.values.isEmpty()) {
2122d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            String[] propertyNames = mPropagation.getPropagationProperties();
2123d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (propertyNames == null) {
2124d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                return;
2125d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
2126d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            boolean containsAll = true;
2127d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            for (int i = 0; i < propertyNames.length; i++) {
2128d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                if (!transitionValues.values.containsKey(propertyNames[i])) {
2129d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    containsAll = false;
2130d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    break;
2131d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                }
2132d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
2133d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (!containsAll) {
2134d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                mPropagation.captureValues(transitionValues);
2135d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
2136d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
2137d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
2138d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
2139d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    Transition setSceneRoot(ViewGroup sceneRoot) {
21406ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        mSceneRoot = sceneRoot;
2141d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        return this;
21426ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
21436ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
2144b7a7fc9d233bad507ce893882352618b13647058Chet Haase    void setCanRemoveViews(boolean canRemoveViews) {
2145b7a7fc9d233bad507ce893882352618b13647058Chet Haase        mCanRemoveViews = canRemoveViews;
2146b7a7fc9d233bad507ce893882352618b13647058Chet Haase    }
2147b7a7fc9d233bad507ce893882352618b13647058Chet Haase
21480a778eda690a66173733a63622886e888d405c45George Mount    public boolean canRemoveViews() {
21490a778eda690a66173733a63622886e888d405c45George Mount        return mCanRemoveViews;
21500a778eda690a66173733a63622886e888d405c45George Mount    }
21510a778eda690a66173733a63622886e888d405c45George Mount
2152d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    /**
2153d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount     * Sets the shared element names -- a mapping from a name at the start state to
2154d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount     * a different name at the end state.
2155d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount     * @hide
2156d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount     */
2157d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    public void setNameOverrides(ArrayMap<String, String> overrides) {
2158d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        mNameOverrides = overrides;
2159d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    }
2160d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount
2161d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    /** @hide */
2162d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    public ArrayMap<String, String> getNameOverrides() {
2163d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        return mNameOverrides;
2164d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount    }
2165d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount
2166b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    /** @hide */
2167b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    public void forceVisibility(int visibility, boolean isStartValue) {}
2168b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount
2169faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    @Override
2170faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public String toString() {
2171faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return toString("");
2172faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
2173faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
21746ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    @Override
21756ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    public Transition clone() {
21766ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        Transition clone = null;
21776ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        try {
21786ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            clone = (Transition) super.clone();
2179199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            clone.mAnimators = new ArrayList<Animator>();
21807660d121b2ef21164ed33e6091e5dd50f5d0f939Chet Haase            clone.mStartValues = new TransitionValuesMaps();
21817660d121b2ef21164ed33e6091e5dd50f5d0f939Chet Haase            clone.mEndValues = new TransitionValuesMaps();
21824d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            clone.mStartValuesList = null;
21834d1ecf5daf6ad0b5420f3f3657e2cbaeea630240George Mount            clone.mEndValuesList = null;
21846ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        } catch (CloneNotSupportedException e) {}
21856ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
21866ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        return clone;
21876ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
21886ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
2189199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
2190199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns the name of this Transition. This name is used internally to distinguish
2191199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * between different transitions to determine when interrupting transitions overlap.
2192d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * For example, a ChangeBounds running on the same target view as another ChangeBounds
2193d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * should determine whether the old transition is animating to different end values
2194d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * and should be canceled in favor of the new transition.
2195199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
2196199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * <p>By default, a Transition's name is simply the value of {@link Class#getName()},
2197199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * but subclasses are free to override and return something different.</p>
2198199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
2199199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return The name of this transition.
2200199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
2201199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public String getName() {
2202199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return mName;
2203199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
2204199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
2205faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    String toString(String indent) {
2206faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        String result = indent + getClass().getSimpleName() + "@" +
2207faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                Integer.toHexString(hashCode()) + ": ";
2208c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mDuration != -1) {
2209c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "dur(" + mDuration + ") ";
2210c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
2211c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mStartDelay != -1) {
2212c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "dly(" + mStartDelay + ") ";
2213c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
2214c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        if (mInterpolator != null) {
2215c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "interp(" + mInterpolator + ") ";
2216c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase        }
2217d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        if (mTargetIds.size() > 0 || mTargets.size() > 0) {
2218c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += "tgts(";
2219d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargetIds.size() > 0) {
2220d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargetIds.size(); ++i) {
2221c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (i > 0) {
2222c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        result += ", ";
2223c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
2224d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    result += mTargetIds.get(i);
2225faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
2226faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
2227d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase            if (mTargets.size() > 0) {
2228d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                for (int i = 0; i < mTargets.size(); ++i) {
2229c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    if (i > 0) {
2230c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                        result += ", ";
2231c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase                    }
2232d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase                    result += mTargets.get(i);
2233faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
2234faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
2235c43524f3869cc0d36974fce61986017093f2ecd2Chet Haase            result += ")";
2236faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
2237faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return result;
2238faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
2239faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2240faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
2241faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * A transition listener receives notifications from a transition.
2242199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Notifications indicate transition lifecycle events.
2243faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
2244faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public static interface TransitionListener {
2245faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
2246faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the start of the transition.
2247faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
2248faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The started transition.
2249faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
2250faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionStart(Transition transition);
2251faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2252faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
2253faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the end of the transition. Canceled transitions
2254faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * will always notify listeners of both the cancellation and end
2255199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * events. That is, {@link #onTransitionEnd(Transition)} is always called,
2256faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * regardless of whether the transition was canceled or played
2257faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * through to completion.
2258faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
2259faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The transition which reached its end.
2260faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
2261faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionEnd(Transition transition);
2262faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2263faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        /**
2264faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * Notification about the cancellation of the transition.
2265d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that cancel may be called by a parent {@link TransitionSet} on
2266199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
2267199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state on target objects which was set at
2268d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
2269d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * createAnimator()} time.
2270faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         *
2271faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         * @param transition The transition which was canceled.
2272faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase         */
2273faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        void onTransitionCancel(Transition transition);
2274199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
2275199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        /**
2276199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * Notification when a transition is paused.
2277d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that createAnimator() may be called by a parent {@link TransitionSet} on
2278199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
2279199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state on target objects which was set at
2280d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
2281d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * createAnimator()} time.
2282199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         *
2283199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * @param transition The transition which was paused.
2284199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         */
2285199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        void onTransitionPause(Transition transition);
2286199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
2287199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        /**
2288199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * Notification when a transition is resumed.
2289d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase         * Note that resume() may be called by a parent {@link TransitionSet} on
2290199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * a child transition which has not yet started. This allows the child
2291199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * transition to restore state which may have changed in an earlier call
2292199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * to {@link #onTransitionPause(Transition)}.
2293199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         *
2294199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         * @param transition The transition which was resumed.
2295199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase         */
2296199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        void onTransitionResume(Transition transition);
2297faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
2298faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2299faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
2300faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * Utility adapter class to avoid having to override all three methods
2301faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * whenever someone just wants to listen for a single event.
2302faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
2303faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * @hide
2304faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     * */
2305faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    public static class TransitionListenerAdapter implements TransitionListener {
2306faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
2307faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionStart(Transition transition) {
2308faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
2309faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2310faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
2311faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionEnd(Transition transition) {
2312faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
2313faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2314faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        @Override
2315faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        public void onTransitionCancel(Transition transition) {
2316faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
2317199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
2318199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        @Override
2319199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        public void onTransitionPause(Transition transition) {
2320199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
2321199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
2322199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        @Override
2323199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        public void onTransitionResume(Transition transition) {
2324199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
2325faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
2326faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
2327199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
2328199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Holds information about each animator used when a new transition starts
2329199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * while other transitions are still running to determine whether a running
2330199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * animation should be canceled or a new animation noop'd. The structure holds
2331199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * information about the state that an animation is going to, to be compared to
2332199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * end state of a new animation.
23330a778eda690a66173733a63622886e888d405c45George Mount     * @hide
2334199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
23350a778eda690a66173733a63622886e888d405c45George Mount    public static class AnimationInfo {
23360a778eda690a66173733a63622886e888d405c45George Mount        public View view;
2337199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        String name;
2338199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        TransitionValues values;
2339cf68aad3164303df59b2a669d186a94533c9c743George Mount        WindowId windowId;
23404c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        Transition transition;
2341199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
23424c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        AnimationInfo(View view, String name, Transition transition,
23434c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount                WindowId windowId, TransitionValues values) {
2344199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.view = view;
2345199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.name = name;
2346199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            this.values = values;
2347cf68aad3164303df59b2a669d186a94533c9c743George Mount            this.windowId = windowId;
23484c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount            this.transition = transition;
2349199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
2350199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
2351ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
2352ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    /**
2353ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * Utility class for managing typed ArrayLists efficiently. In particular, this
2354ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * can be useful for lists that we don't expect to be used often (eg, the exclude
2355ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * lists), so we'd like to keep them nulled out by default. This causes the code to
2356ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * become tedious, with constant null checks, code to allocate when necessary,
2357ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * and code to null out the reference when the list is empty. This class encapsulates
2358ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * all of that functionality into simple add()/remove() methods which perform the
2359ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * necessary checks, allocation/null-out as appropriate, and return the
2360ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     * resulting list.
2361ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase     */
2362ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    private static class ArrayListManager {
2363ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
2364ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        /**
2365ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Add the specified item to the list, returning the resulting list.
2366ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * The returned list can either the be same list passed in or, if that
2367ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list was null, the new list that was created.
2368ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         *
2369ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Note that the list holds unique items; if the item already exists in the
2370ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list, the list is not modified.
2371ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         */
2372ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        static <T> ArrayList<T> add(ArrayList<T> list, T item) {
2373ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (list == null) {
2374ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list = new ArrayList<T>();
2375ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
2376ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (!list.contains(item)) {
2377ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list.add(item);
2378ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
2379ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return list;
2380ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
2381ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
2382ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        /**
2383ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * Remove the specified item from the list, returning the resulting list.
2384ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * The returned list can either the be same list passed in or, if that
2385ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         * list becomes empty as a result of the remove(), the new list was created.
2386ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase         */
2387ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        static <T> ArrayList<T> remove(ArrayList<T> list, T item) {
2388ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            if (list != null) {
2389ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                list.remove(item);
2390ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                if (list.isEmpty()) {
2391ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                    list = null;
2392ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase                }
2393ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            }
2394ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase            return list;
2395ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase        }
2396ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase    }
2397ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase
2398d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
2399d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Class to get the epicenter of Transition. Use
2400d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #setEpicenterCallback(android.transition.Transition.EpicenterCallback)} to
2401d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * set the callback used to calculate the epicenter of the Transition. Override
2402d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #getEpicenter()} to return the rectangular region in screen coordinates of
2403d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the epicenter of the transition.
2404d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @see #setEpicenterCallback(android.transition.Transition.EpicenterCallback)
2405d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
2406d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public static abstract class EpicenterCallback {
2407d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
2408d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        /**
2409d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * Implementers must override to return the epicenter of the Transition in screen
2410d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * coordinates. Transitions like {@link android.transition.Explode} depend upon
2411d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * an epicenter for the Transition. In Explode, Views move toward or away from the
2412d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * center of the epicenter Rect along the vector between the epicenter and the center
2413d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * of the View appearing and disappearing. Some Transitions, such as
2414d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * {@link android.transition.Fade} pay no attention to the epicenter.
2415d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         *
2416d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * @param transition The transition for which the epicenter applies.
2417d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * @return The Rect region of the epicenter of <code>transition</code> or null if
2418d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         * there is no epicenter.
2419d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount         */
2420dc21d3b2804c24fe29ec860796d11185901364c4George Mount        public abstract Rect onGetEpicenter(Transition transition);
2421d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
2422faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase}
2423