1c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki/*
2c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Copyright (C) 2016 The Android Open Source Project
3c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *
4c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Licensed under the Apache License, Version 2.0 (the "License");
5c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * you may not use this file except in compliance with the License.
6c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * You may obtain a copy of the License at
7c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *
8c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *      http://www.apache.org/licenses/LICENSE-2.0
9c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *
10c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Unless required by applicable law or agreed to in writing, software
11c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * distributed under the License is distributed on an "AS IS" BASIS,
12c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * See the License for the specific language governing permissions and
14c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * limitations under the License.
15c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */
16c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.transition;
18c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
21c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.animation.Animator;
224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Arakiimport android.animation.AnimatorListenerAdapter;
23c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.animation.TimeInterpolator;
248158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.content.Context;
258158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.content.res.TypedArray;
268158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.content.res.XmlResourceParser;
27317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Arakiimport android.graphics.Path;
284c904b38c763179727b9b5ea7a80454630545663Yuichi Arakiimport android.graphics.Rect;
298158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.util.AttributeSet;
304e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Arakiimport android.util.Log;
314e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Arakiimport android.util.SparseArray;
324c904b38c763179727b9b5ea7a80454630545663Yuichi Arakiimport android.util.SparseIntArray;
338158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.view.InflateException;
34c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.SurfaceView;
35c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.TextureView;
36c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.View;
37c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.ViewGroup;
388158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.view.animation.AnimationUtils;
394e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Arakiimport android.widget.ListView;
40c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.widget.Spinner;
41c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
424d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.annotation.IdRes;
434d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.annotation.IntDef;
444d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.annotation.NonNull;
454d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.annotation.Nullable;
464d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.annotation.RestrictTo;
474d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.collection.ArrayMap;
484d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.collection.LongSparseArray;
494d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.core.content.res.TypedArrayUtils;
504d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.core.view.ViewCompat;
514d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikas
52756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Arakiimport java.lang.annotation.Retention;
53756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Arakiimport java.lang.annotation.RetentionPolicy;
544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Arakiimport java.util.ArrayList;
55c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport java.util.List;
568158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport java.util.StringTokenizer;
57c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
58c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki/**
59c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * A Transition holds information about animations that will be run on its
60c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * targets during a scene change. Subclasses of this abstract class may
61c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * choreograph several child transitions ({@link TransitionSet} or they may
62c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * perform custom animations themselves. Any Transition has two main jobs:
63c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * (1) capture property values, and (2) play animations based on changes to
64c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * captured property values. A custom transition knows what property values
65c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * on View objects are of interest to it, and also knows how to animate
66c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * changes to those values. For example, the {@link Fade} transition tracks
67c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * changes to visibility-related properties and is able to construct and run
68c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * animations that fade items in or out based on changes to those properties.
69c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *
70c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * <p>Note: Transitions may not work correctly with either {@link SurfaceView}
71c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * or {@link TextureView}, due to the way that these views are displayed
72c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * on the screen. For SurfaceView, the problem is that the view is updated from
73c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * a non-UI thread, so changes to the view due to transitions (such as moving
74c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * and resizing the view) may be out of sync with the display inside those bounds.
75c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * TextureView is more compatible with transitions in general, but some
76c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * specific transitions (such as {@link Fade}) may not be compatible
779562a3b639225d406d736b64a12e2d75459259e3Alan Viverette * with TextureView because they rely on {@link android.view.ViewOverlay}
789562a3b639225d406d736b64a12e2d75459259e3Alan Viverette * functionality, which does not currently work with TextureView.</p>
79c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *
808158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * <p>Transitions can be declared in XML resource files inside the <code>res/transition</code>
818158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * directory. Transition resources consist of a tag name for one of the Transition
828158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * subclasses along with attributes to define some of the attributes of that transition.
838158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * For example, here is a minimal resource file that declares a {@link ChangeBounds}
848158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * transition:</p>
858158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *
868158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * <pre>
878158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *     &lt;changeBounds/&gt;
888158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * </pre>
898158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *
908158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * <p>Note that attributes for the transition are not required, just as they are
918158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * optional when declared in code; Transitions created from XML resources will use
928158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * the same defaults as their code-created equivalents. Here is a slightly more
938158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * elaborate example which declares a {@link TransitionSet} transition with
948158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * {@link ChangeBounds} and {@link Fade} child transitions:</p>
958158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *
968158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * <pre>
978158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *     &lt;transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
988158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *          android:transitionOrdering="sequential"&gt;
998158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *         &lt;changeBounds/&gt;
1008158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *         &lt;fade android:fadingMode="fade_out"&gt;
1018158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *             &lt;targets&gt;
1028158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *                 &lt;target android:targetId="@id/grayscaleContainer"/&gt;
1038158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *             &lt;/targets&gt;
1048158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *         &lt;/fade&gt;
1058158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *     &lt;/transitionSet&gt;
1068158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * </pre>
1078158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki *
1088158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * <p>In this example, the transitionOrdering attribute is used on the TransitionSet
1098158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * object to change from the default {@link TransitionSet#ORDERING_TOGETHER} behavior
1108158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * to be {@link TransitionSet#ORDERING_SEQUENTIAL} instead. Also, the {@link Fade}
1118158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * transition uses a fadingMode of {@link Fade#OUT} instead of the default
1128158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * out-in behavior. Finally, note the use of the <code>targets</code> sub-tag, which
1138158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * takes a set of {code target} tags, each of which lists a specific <code>targetId</code> which
1148158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * this transition acts upon. Use of targets is optional, but can be used to either limit the time
1158158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * spent checking attributes on unchanging views, or limiting the types of animations run on
1168158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * specific views. In this case, we know that only the <code>grayscaleContainer</code> will be
1178158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * disappearing, so we choose to limit the {@link Fade} transition to only that view.</p>
118c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */
1194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Arakipublic abstract class Transition implements Cloneable {
1204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
1214e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private static final String LOG_TAG = "Transition";
1224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    static final boolean DBG = false;
1234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
124756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
125756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * With {@link #setMatchOrder(int...)}, chooses to match by View instance.
126756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
127756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public static final int MATCH_INSTANCE = 0x1;
128756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private static final int MATCH_FIRST = MATCH_INSTANCE;
129756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
130756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
131756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * With {@link #setMatchOrder(int...)}, chooses to match by
132756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * {@link android.view.View#getTransitionName()}. Null names will not be matched.
133756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
134756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public static final int MATCH_NAME = 0x2;
135756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
136756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
137756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * With {@link #setMatchOrder(int...)}, chooses to match by
138756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * {@link android.view.View#getId()}. Negative IDs will not be matched.
139756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
140756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public static final int MATCH_ID = 0x3;
141756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
142756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
143756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * With {@link #setMatchOrder(int...)}, chooses to match by the {@link android.widget.Adapter}
144756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * item id. When {@link android.widget.Adapter#hasStableIds()} returns false, no match
145756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * will be made for items.
146756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
147756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public static final int MATCH_ITEM_ID = 0x4;
148756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
149756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private static final int MATCH_LAST = MATCH_ITEM_ID;
150756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
151756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /** @hide */
152756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @RestrictTo(LIBRARY_GROUP)
153756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @IntDef({MATCH_INSTANCE, MATCH_NAME, MATCH_ID, MATCH_ITEM_ID})
154756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @Retention(RetentionPolicy.SOURCE)
155756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public @interface MatchOrder {
156756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
157756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1588158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    private static final String MATCH_INSTANCE_STR = "instance";
1598158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    private static final String MATCH_NAME_STR = "name";
1608158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    private static final String MATCH_ID_STR = "id";
1618158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    private static final String MATCH_ITEM_ID_STR = "itemId";
1628158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki
163756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private static final int[] DEFAULT_MATCH_ORDER = {
164756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            MATCH_NAME,
165756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            MATCH_INSTANCE,
166756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            MATCH_ID,
167756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            MATCH_ITEM_ID,
168756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    };
169756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
170317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki    private static final PathMotion STRAIGHT_PATH_MOTION = new PathMotion() {
171317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki        @Override
172317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki        public Path getPath(float startX, float startY, float endX, float endY) {
173317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki            Path path = new Path();
174317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki            path.moveTo(startX, startY);
175317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki            path.lineTo(endX, endY);
176317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki            return path;
177317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki        }
178317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki    };
179317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki
1804e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private String mName = getClass().getName();
1814e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
1824e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private long mStartDelay = -1;
1834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    long mDuration = -1;
1844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private TimeInterpolator mInterpolator = null;
1854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    ArrayList<Integer> mTargetIds = new ArrayList<>();
1864e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    ArrayList<View> mTargets = new ArrayList<>();
187756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private ArrayList<String> mTargetNames = null;
188756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private ArrayList<Class> mTargetTypes = null;
1894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<Integer> mTargetIdExcludes = null;
1904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<View> mTargetExcludes = null;
1914e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<Class> mTargetTypeExcludes = null;
192756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private ArrayList<String> mTargetNameExcludes = null;
1934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<Integer> mTargetIdChildExcludes = null;
1944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<View> mTargetChildExcludes = null;
1954e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<Class> mTargetTypeChildExcludes = null;
1964e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private TransitionValuesMaps mStartValues = new TransitionValuesMaps();
1974e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private TransitionValuesMaps mEndValues = new TransitionValuesMaps();
1984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    TransitionSet mParent = null;
199756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private int[] mMatchOrder = DEFAULT_MATCH_ORDER;
200756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private ArrayList<TransitionValues> mStartValuesList; // only valid after playTransition starts
201756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private ArrayList<TransitionValues> mEndValuesList; // only valid after playTransitions starts
2024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
2034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // Per-animator information used for later canceling when future transitions overlap
2044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private static ThreadLocal<ArrayMap<Animator, Transition.AnimationInfo>> sRunningAnimators =
2054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            new ThreadLocal<>();
2064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
2074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // Scene Root is set at createAnimator() time in the cloned Transition
2084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ViewGroup mSceneRoot = null;
2094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
2104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // Whether removing views from their parent is possible. This is only for views
2114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // in the start scene, which are no longer in the view hierarchy. This property
2124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // is determined by whether the previous Scene was created from a layout
2134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // resource, and thus the views from the exited scene are going away anyway
2144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // and can be removed as necessary to achieve a particular effect, such as
2154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // removing them from parents to add them to overlays.
2164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    boolean mCanRemoveViews = false;
2174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
2184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // Track all animators in use in case the transition gets canceled and needs to
2194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // cancel running animators
2204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<Animator> mCurrentAnimators = new ArrayList<>();
221c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
2224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // Number of per-target instances of this Transition currently running. This count is
2234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // determined by calls to start() and end()
2244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private int mNumInstances = 0;
2254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
2264e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // Whether this transition is currently paused, due to a call to pause()
2274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private boolean mPaused = false;
2284e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
2294e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // Whether this transition has ended. Used to avoid pause/resume on transitions
2304e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // that have completed
2314e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private boolean mEnded = false;
2324e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
2334e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // The set of listeners to be sent transition lifecycle events.
2344e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<Transition.TransitionListener> mListeners = null;
2354e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
2364e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // The set of animators collected from calls to createAnimator(),
2374e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    // to be run in runAnimators()
2384e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<Animator> mAnimators = new ArrayList<>();
239c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
2404c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    // The function for calculating the Animation start delay.
2414c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    TransitionPropagation mPropagation;
2424c904b38c763179727b9b5ea7a80454630545663Yuichi Araki
2434c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    // The rectangular region for Transitions like Explode and TransitionPropagations
2444c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    // like CircularPropagation
2454c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    private EpicenterCallback mEpicenterCallback;
2464c904b38c763179727b9b5ea7a80454630545663Yuichi Araki
247756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    // For Fragment shared element transitions, linking views explicitly by mismatching
248756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    // transitionNames.
249756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private ArrayMap<String, String> mNameOverrides;
250756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
251317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki    // The function used to interpolate along two-dimensional points. Typically used
252317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki    // for adding curves to x/y View motion.
253317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki    private PathMotion mPathMotion = STRAIGHT_PATH_MOTION;
254317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki
255c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
256c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Constructs a Transition object with no target objects. A transition with
257c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * no targets defaults to running on all target objects in the scene hierarchy
258c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * (if the transition is not contained in a TransitionSet), or all target
259c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * objects passed down from its parent (if it is in a TransitionSet).
260c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
261c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public Transition() {
262c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
263c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
264c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
2658158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki     * Perform inflation from XML and apply a class-specific base style from a
2668158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki     * theme attribute or style resource. This constructor of Transition allows
2678158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki     * subclasses to use their own base style when they are inflating.
2688158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki     *
2698158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki     * @param context The Context the transition is running in, through which it can
2708158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki     *                access the current theme, resources, etc.
2718158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki     * @param attrs   The attributes of the XML tag that is inflating the transition.
2728158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki     */
2738158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    public Transition(Context context, AttributeSet attrs) {
2748158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        TypedArray a = context.obtainStyledAttributes(attrs, Styleable.TRANSITION);
2758158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        XmlResourceParser parser = (XmlResourceParser) attrs;
2768158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        long duration = TypedArrayUtils.getNamedInt(a, parser, "duration",
2778158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                Styleable.Transition.DURATION, -1);
2788158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        if (duration >= 0) {
2798158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            setDuration(duration);
2808158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        }
2818158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        long startDelay = TypedArrayUtils.getNamedInt(a, parser, "startDelay",
2828158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                Styleable.Transition.START_DELAY, -1);
2838158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        if (startDelay > 0) {
2848158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            setStartDelay(startDelay);
2858158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        }
2868158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        final int resId = TypedArrayUtils.getNamedResourceId(a, parser, "interpolator",
2878158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                Styleable.Transition.INTERPOLATOR, 0);
2888158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        if (resId > 0) {
2898158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            setInterpolator(AnimationUtils.loadInterpolator(context, resId));
2908158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        }
2918158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        String matchOrder = TypedArrayUtils.getNamedString(a, parser, "matchOrder",
2928158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                Styleable.Transition.MATCH_ORDER);
2938158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        if (matchOrder != null) {
2948158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            setMatchOrder(parseMatchOrder(matchOrder));
2958158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        }
2968158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        a.recycle();
2978158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    }
2988158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki
2998158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    @MatchOrder
3008158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    private static int[] parseMatchOrder(String matchOrderString) {
3018158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        StringTokenizer st = new StringTokenizer(matchOrderString, ",");
3028158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        @MatchOrder
3038158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        int[] matches = new int[st.countTokens()];
3048158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        int index = 0;
3058158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        while (st.hasMoreTokens()) {
3068158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            String token = st.nextToken().trim();
3078158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            if (MATCH_ID_STR.equalsIgnoreCase(token)) {
3088158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                matches[index] = Transition.MATCH_ID;
3098158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            } else if (MATCH_INSTANCE_STR.equalsIgnoreCase(token)) {
3108158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                matches[index] = Transition.MATCH_INSTANCE;
3118158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            } else if (MATCH_NAME_STR.equalsIgnoreCase(token)) {
3128158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                matches[index] = Transition.MATCH_NAME;
3138158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            } else if (MATCH_ITEM_ID_STR.equalsIgnoreCase(token)) {
3148158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                matches[index] = Transition.MATCH_ITEM_ID;
3158158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            } else if (token.isEmpty()) {
3168158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                @MatchOrder
3178158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                int[] smallerMatches = new int[matches.length - 1];
3188158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                System.arraycopy(matches, 0, smallerMatches, 0, index);
3198158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                matches = smallerMatches;
3208158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                index--;
3218158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            } else {
3228158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                throw new InflateException("Unknown match type in matchOrder: '" + token + "'");
3238158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            }
3248158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            index++;
3258158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        }
3268158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        return matches;
3278158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    }
3288158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki
3298158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    /**
3304e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Sets the duration of this transition. By default, there is no duration
3314e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * (indicated by a negative number), which means that the Animator created by
3324e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the transition will have its own specified duration. If the duration of a
3334e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Transition is set, that duration will override the Animator duration.
334c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
3354e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param duration The length of the animation, in milliseconds.
336c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @return This transition object.
337c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
338cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @NonNull
3394e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition setDuration(long duration) {
3404e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mDuration = duration;
341c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return this;
342c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
343c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
344c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
3454e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Returns the duration set on this transition. If no duration has been set,
3464e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the returned value will be negative, indicating that resulting animators will
3474e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * retain their own durations.
348c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
3494e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return The duration set on this transition, in milliseconds, if one has been
3504e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * set, otherwise returns a negative number.
3514e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
3524e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public long getDuration() {
3534e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return mDuration;
3544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
3554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
3564e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
3574e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Sets the startDelay of this transition. By default, there is no delay
3584e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * (indicated by a negative number), which means that the Animator created by
3594e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the transition will have its own specified startDelay. If the delay of a
3604e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Transition is set, that delay will override the Animator delay.
361c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
3624e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param startDelay The length of the delay, in milliseconds.
3634e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return This transition object.
364c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
365cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @NonNull
3664e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition setStartDelay(long startDelay) {
3674e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mStartDelay = startDelay;
368c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return this;
369c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
370c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
371c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
3724e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Returns the startDelay set on this transition. If no startDelay has been set,
3734e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the returned value will be negative, indicating that resulting animators will
3744e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * retain their own startDelays.
375c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
3764e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return The startDelay set on this transition, in milliseconds, if one has
3774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * been set, otherwise returns a negative number.
3784e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
3794e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public long getStartDelay() {
3804e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return mStartDelay;
3814e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
3824e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
3834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
3844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Sets the interpolator of this transition. By default, the interpolator
3854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * is null, which means that the Animator created by the transition
3864e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * will have its own specified interpolator. If the interpolator of a
3874e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Transition is set, that interpolator will override the Animator interpolator.
388c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
3894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param interpolator The time interpolator used by the transition
3904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return This transition object.
391c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
392cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @NonNull
3934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition setInterpolator(@Nullable TimeInterpolator interpolator) {
3944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mInterpolator = interpolator;
395c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return this;
396c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
397c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
398c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
3994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Returns the interpolator set on this transition. If no interpolator has been set,
4004e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the returned value will be null, indicating that resulting animators will
4014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * retain their own interpolators.
402c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
4034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return The interpolator set on this transition, if one has been set, otherwise
4044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * returns null.
405c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
4064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @Nullable
4074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public TimeInterpolator getInterpolator() {
4084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return mInterpolator;
4094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
410c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
411c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
4124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Returns the set of property names used stored in the {@link TransitionValues}
4134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * object passed into {@link #captureStartValues(TransitionValues)} that
4144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * this transition cares about for the purposes of canceling overlapping animations.
4154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * When any transition is started on a given scene root, all transitions
4164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * currently running on that same scene root are checked to see whether the
4174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * properties on which they based their animations agree with the end values of
4184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the same properties in the new transition. If the end values are not equal,
4194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * then the old animation is canceled since the new transition will start a new
4204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * animation to these new values. If the values are equal, the old animation is
4214e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * allowed to continue and no new animation is started for that transition.
422c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
4234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <p>A transition does not need to override this method. However, not doing so
4244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * will mean that the cancellation logic outlined in the previous paragraph
4254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * will be skipped for that transition, possibly leading to artifacts as
4264e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * old transitions and new transitions on the same targets run in parallel,
4274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * animating views toward potentially different end values.</p>
428c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
4294e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return An array of property names as described in the class documentation for
4304e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * {@link TransitionValues}. The default implementation returns <code>null</code>.
431c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
4324e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @Nullable
4334e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public String[] getTransitionProperties() {
4344e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return null;
4354e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
436c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
437c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
438c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * This method creates an animation that will be run for this transition
439c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * given the information in the startValues and endValues structures captured
440c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * earlier for the start and end scenes. Subclasses of Transition should override
441c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * this method. The method should only be called by the transition system; it is
442c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * not intended to be called from external classes.
443c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
444c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>This method is called by the transition's parent (all the way up to the
445c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * topmost Transition in the hierarchy) with the sceneRoot and start/end
446c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * values that the transition may need to set up initial target values
447c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * and construct an appropriate animation. For example, if an overall
448c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Transition is a {@link TransitionSet} consisting of several
449c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * child transitions in sequence, then some of the child transitions may
450c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * want to set initial values on target views prior to the overall
451c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Transition commencing, to put them in an appropriate state for the
452c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * delay between that start and the child Transition start time. For
453c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * example, a transition that fades an item in may wish to set the starting
454c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * alpha value to 0, to avoid it blinking in prior to the transition
455c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * actually starting the animation. This is necessary because the scene
456c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * change that triggers the Transition will automatically set the end-scene
457c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * on all target views, so a Transition that wants to animate from a
458c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * different value should set that value prior to returning from this method.</p>
459c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
460c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>Additionally, a Transition can perform logic to determine whether
461c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * the transition needs to run on the given target and start/end values.
462c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * For example, a transition that resizes objects on the screen may wish
463c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * to avoid running for views which are not present in either the start
464c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * or end scenes.</p>
465c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
466c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>If there is an animator created and returned from this method, the
467c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * transition mechanism will apply any applicable duration, startDelay,
468c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * and interpolator to that animation and start it. A return value of
469c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <code>null</code> indicates that no animation should run. The default
470c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * implementation returns null.</p>
471c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
472c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>The method is called for every applicable target object, which is
473c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * stored in the {@link TransitionValues#view} field.</p>
474c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
475c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param sceneRoot   The root of the transition hierarchy.
476c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param startValues The values for a specific target in the start scene.
477c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param endValues   The values for the target in the end scene.
478c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @return A Animator to be started at the appropriate time in the
479c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * overall transition for this scene change. A null value means no animation
480c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * should be run.
481c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
482cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @Nullable
483d5b720e30a9d82b5f81ec8eac2803e213f2f1c41Yuichi Araki    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
484d5b720e30a9d82b5f81ec8eac2803e213f2f1c41Yuichi Araki            @Nullable TransitionValues startValues, @Nullable TransitionValues endValues) {
485d5b720e30a9d82b5f81ec8eac2803e213f2f1c41Yuichi Araki        return null;
486d5b720e30a9d82b5f81ec8eac2803e213f2f1c41Yuichi Araki    }
487c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
488c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
489756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Sets the order in which Transition matches View start and end values.
490756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * <p>
491756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * The default behavior is to match first by {@link android.view.View#getTransitionName()},
492756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * then by View instance, then by {@link android.view.View#getId()} and finally
493756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * by its item ID if it is in a direct child of ListView. The caller can
494756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * choose to have only some or all of the values of {@link #MATCH_INSTANCE},
495756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * {@link #MATCH_NAME}, {@link #MATCH_ITEM_ID}, and {@link #MATCH_ID}. Only
496756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * the match algorithms supplied will be used to determine whether Views are the
497756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * the same in both the start and end Scene. Views that do not match will be considered
498756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * as entering or leaving the Scene.
499756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * </p>
500c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
501756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @param matches A list of zero or more of {@link #MATCH_INSTANCE},
502756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *                {@link #MATCH_NAME}, {@link #MATCH_ITEM_ID}, and {@link #MATCH_ID}.
503756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *                If none are provided, then the default match order will be set.
504c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
505756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public void setMatchOrder(@MatchOrder int... matches) {
506756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (matches == null || matches.length == 0) {
507756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            mMatchOrder = DEFAULT_MATCH_ORDER;
508756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        } else {
509756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            for (int i = 0; i < matches.length; i++) {
510756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                int match = matches[i];
511756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (!isValidMatch(match)) {
512756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    throw new IllegalArgumentException("matches contains invalid value");
513756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                }
514756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (alreadyContains(matches, i)) {
515756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    throw new IllegalArgumentException("matches contains a duplicate value");
516756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                }
517756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
518756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            mMatchOrder = matches.clone();
5194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
520756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
521756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
522756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private static boolean isValidMatch(int match) {
523756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return (match >= MATCH_FIRST && match <= MATCH_LAST);
524756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
525756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
526756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private static boolean alreadyContains(int[] array, int searchIndex) {
527756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        int value = array[searchIndex];
528756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        for (int i = 0; i < searchIndex; i++) {
529756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (array[i] == value) {
530756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                return true;
5314e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
532756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
533756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return false;
534756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
535756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
536756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
537756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Match start/end values by View instance. Adds matched values to mStartValuesList
538756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd.
539756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
540756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private void matchInstances(ArrayMap<View, TransitionValues> unmatchedStart,
541756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            ArrayMap<View, TransitionValues> unmatchedEnd) {
542756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        for (int i = unmatchedStart.size() - 1; i >= 0; i--) {
543756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            View view = unmatchedStart.keyAt(i);
544c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki            if (view != null && isValidTarget(view)) {
545c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki                TransitionValues end = unmatchedEnd.remove(view);
546c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki                if (end != null && end.view != null && isValidTarget(end.view)) {
547c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki                    TransitionValues start = unmatchedStart.removeAt(i);
548c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki                    mStartValuesList.add(start);
549c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki                    mEndValuesList.add(end);
550c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki                }
551756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
552756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
553756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
554756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
555756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
556756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Match start/end values by Adapter item ID. Adds matched values to mStartValuesList
557756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
558756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * startItemIds and endItemIds as a guide for which Views have unique item IDs.
559756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
560756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private void matchItemIds(ArrayMap<View, TransitionValues> unmatchedStart,
561756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            ArrayMap<View, TransitionValues> unmatchedEnd,
562756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            LongSparseArray<View> startItemIds, LongSparseArray<View> endItemIds) {
563756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        int numStartIds = startItemIds.size();
564756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        for (int i = 0; i < numStartIds; i++) {
565756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            View startView = startItemIds.valueAt(i);
566c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki            if (startView != null && isValidTarget(startView)) {
567756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                View endView = endItemIds.get(startItemIds.keyAt(i));
568c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki                if (endView != null && isValidTarget(endView)) {
569756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    TransitionValues startValues = unmatchedStart.get(startView);
570756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    TransitionValues endValues = unmatchedEnd.get(endView);
571756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    if (startValues != null && endValues != null) {
572756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        mStartValuesList.add(startValues);
573756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        mEndValuesList.add(endValues);
574756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        unmatchedStart.remove(startView);
575756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        unmatchedEnd.remove(endView);
5764e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
5774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
5784e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
5794e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
580756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
581756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
582756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
583756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Match start/end values by Adapter view ID. Adds matched values to mStartValuesList
584756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
585756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * startIds and endIds as a guide for which Views have unique IDs.
586756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
587756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private void matchIds(ArrayMap<View, TransitionValues> unmatchedStart,
588756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            ArrayMap<View, TransitionValues> unmatchedEnd,
589756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            SparseArray<View> startIds, SparseArray<View> endIds) {
590756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        int numStartIds = startIds.size();
591756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        for (int i = 0; i < numStartIds; i++) {
592756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            View startView = startIds.valueAt(i);
593756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (startView != null && isValidTarget(startView)) {
594756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                View endView = endIds.get(startIds.keyAt(i));
595756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (endView != null && isValidTarget(endView)) {
596756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    TransitionValues startValues = unmatchedStart.get(startView);
597756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    TransitionValues endValues = unmatchedEnd.get(endView);
598756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    if (startValues != null && endValues != null) {
599756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        mStartValuesList.add(startValues);
600756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        mEndValuesList.add(endValues);
601756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        unmatchedStart.remove(startView);
602756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        unmatchedEnd.remove(endView);
603756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    }
604756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                }
6054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
6064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
607756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
608756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
609756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
610756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Match start/end values by Adapter transitionName. Adds matched values to mStartValuesList
611756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
612756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * startNames and endNames as a guide for which Views have unique transitionNames.
613756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
614756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private void matchNames(ArrayMap<View, TransitionValues> unmatchedStart,
615756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            ArrayMap<View, TransitionValues> unmatchedEnd,
616756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            ArrayMap<String, View> startNames, ArrayMap<String, View> endNames) {
617756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        int numStartNames = startNames.size();
618756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        for (int i = 0; i < numStartNames; i++) {
619756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            View startView = startNames.valueAt(i);
620756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (startView != null && isValidTarget(startView)) {
621756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                View endView = endNames.get(startNames.keyAt(i));
622756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (endView != null && isValidTarget(endView)) {
623756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    TransitionValues startValues = unmatchedStart.get(startView);
624756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    TransitionValues endValues = unmatchedEnd.get(endView);
625756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    if (startValues != null && endValues != null) {
626756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        mStartValuesList.add(startValues);
627756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        mEndValuesList.add(endValues);
628756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        unmatchedStart.remove(startView);
629756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        unmatchedEnd.remove(endView);
630756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    }
631756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                }
6324e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
6334e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
634756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
635756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
636756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
637756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Adds all values from unmatchedStart and unmatchedEnd to mStartValuesList and mEndValuesList,
638756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * assuming that there is no match between values in the list.
639756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
640756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private void addUnmatched(ArrayMap<View, TransitionValues> unmatchedStart,
641756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            ArrayMap<View, TransitionValues> unmatchedEnd) {
642756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        // Views that only exist in the start Scene
643756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        for (int i = 0; i < unmatchedStart.size(); i++) {
644c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki            final TransitionValues start = unmatchedStart.valueAt(i);
645c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki            if (isValidTarget(start.view)) {
646c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki                mStartValuesList.add(start);
647c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki                mEndValuesList.add(null);
648c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki            }
649756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
650756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
651756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        // Views that only exist in the end Scene
652756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        for (int i = 0; i < unmatchedEnd.size(); i++) {
653c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki            final TransitionValues end = unmatchedEnd.valueAt(i);
654c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki            if (isValidTarget(end.view)) {
655c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki                mEndValuesList.add(end);
656c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki                mStartValuesList.add(null);
657c0b47830d3deb764027d8fbadc2a44e83eedd543Yuichi Araki            }
658756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
659756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
660756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
661756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private void matchStartAndEnd(TransitionValuesMaps startValues,
662756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            TransitionValuesMaps endValues) {
663756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        ArrayMap<View, TransitionValues> unmatchedStart = new ArrayMap<>(startValues.mViewValues);
664756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        ArrayMap<View, TransitionValues> unmatchedEnd = new ArrayMap<>(endValues.mViewValues);
665756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
666756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        for (int i = 0; i < mMatchOrder.length; i++) {
667756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            switch (mMatchOrder[i]) {
668756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                case MATCH_INSTANCE:
669756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    matchInstances(unmatchedStart, unmatchedEnd);
670756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    break;
671756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                case MATCH_NAME:
672756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    matchNames(unmatchedStart, unmatchedEnd,
673756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            startValues.mNameValues, endValues.mNameValues);
674756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    break;
675756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                case MATCH_ID:
676756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    matchIds(unmatchedStart, unmatchedEnd,
677756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            startValues.mIdValues, endValues.mIdValues);
678756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    break;
679756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                case MATCH_ITEM_ID:
680756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    matchItemIds(unmatchedStart, unmatchedEnd,
681756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            startValues.mItemIdValues, endValues.mItemIdValues);
682756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    break;
6834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
6844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
685756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        addUnmatched(unmatchedStart, unmatchedEnd);
686756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
687756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
688756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
689756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * This method, essentially a wrapper around all calls to createAnimator for all
690756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * possible target views, is called with the entire set of start/end
691756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * values. The implementation in Transition iterates through these lists
692756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * and calls {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}
693756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * with each set of start/end values on this transition. The
694756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * TransitionSet subclass overrides this method and delegates it to
695756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * each of its children in succession.
696756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
697756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @hide
698756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
699756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @RestrictTo(LIBRARY_GROUP)
700756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
701756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
702756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            ArrayList<TransitionValues> endValuesList) {
703756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (DBG) {
704756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            Log.d(LOG_TAG, "createAnimators() for " + this);
7054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
7064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
7074c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        long minStartDelay = Long.MAX_VALUE;
7084c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        SparseIntArray startDelays = new SparseIntArray();
709756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        int startValuesListCount = startValuesList.size();
710756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        for (int i = 0; i < startValuesListCount; ++i) {
7114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            TransitionValues start = startValuesList.get(i);
7124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            TransitionValues end = endValuesList.get(i);
713756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (start != null && !start.mTargetedTransitions.contains(this)) {
714756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                start = null;
715756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
716756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (end != null && !end.mTargetedTransitions.contains(this)) {
717756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                end = null;
718756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
719756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (start == null && end == null) {
720756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                continue;
721756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
7224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            // Only bother trying to animate with values that differ between start/end
723dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki            boolean isChanged = start == null || end == null || isTransitionRequired(start, end);
724756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (isChanged) {
725756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (DBG) {
726756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    View view = (end != null) ? end.view : start.view;
727756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    Log.d(LOG_TAG, "  differing start/end values for view " + view);
728756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    if (start == null || end == null) {
729756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        Log.d(LOG_TAG, "    " + ((start == null)
730756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                ? "start null, end non-null" : "start non-null, end null"));
731756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    } else {
732756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        for (String key : start.values.keySet()) {
733756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            Object startValue = start.values.get(key);
734756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            Object endValue = end.values.get(key);
735756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            if (startValue != endValue && !startValue.equals(endValue)) {
736756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                Log.d(LOG_TAG, "    " + key + ": start(" + startValue
737756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                        + "), end(" + endValue + ")");
7384e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                            }
7394e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        }
7404e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
741756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                }
742756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                // TODO: what to do about targetIds and itemIds?
743756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                Animator animator = createAnimator(sceneRoot, start, end);
744756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (animator != null) {
745756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    // Save animation info for future cancellation purposes
746756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    View view;
747756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    TransitionValues infoValues = null;
748756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    if (end != null) {
749756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        view = end.view;
750756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        String[] properties = getTransitionProperties();
751756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        if (view != null && properties != null && properties.length > 0) {
752756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            infoValues = new TransitionValues();
753756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            infoValues.view = view;
754756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            TransitionValues newValues = endValues.mViewValues.get(view);
755756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            if (newValues != null) {
756756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                for (int j = 0; j < properties.length; ++j) {
757756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                    infoValues.values.put(properties[j],
758756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                            newValues.values.get(properties[j]));
7594e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                                }
760756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            }
761756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            int numExistingAnims = runningAnimators.size();
762756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                            for (int j = 0; j < numExistingAnims; ++j) {
763756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                Animator anim = runningAnimators.keyAt(j);
764756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                AnimationInfo info = runningAnimators.get(anim);
765756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                if (info.mValues != null && info.mView == view
766756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                        && info.mName.equals(getName())) {
767756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                    if (info.mValues.equals(infoValues)) {
768756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                        // Favor the old animator
769756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                        animator = null;
770756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                        break;
7714e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                                    }
7724e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                                }
7734e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                            }
7744e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        }
775756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    } else {
776756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        view = start.view;
777756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    }
778756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    if (animator != null) {
7794c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                        if (mPropagation != null) {
7804c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                            long delay = mPropagation.getStartDelay(sceneRoot, this, start, end);
7814c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                            startDelays.put(mAnimators.size(), (int) delay);
7824c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                            minStartDelay = Math.min(delay, minStartDelay);
7834c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                        }
784756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        AnimationInfo info = new AnimationInfo(view, getName(), this,
785756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                                ViewUtils.getWindowId(sceneRoot), infoValues);
786756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        runningAnimators.put(animator, info);
787756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        mAnimators.add(animator);
7884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
7894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
7904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
7914e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
7924c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        if (minStartDelay != 0) {
7934c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            for (int i = 0; i < startDelays.size(); i++) {
7944c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                int index = startDelays.keyAt(i);
7954c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                Animator animator = mAnimators.get(index);
7964c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                long delay = startDelays.valueAt(i) - minStartDelay + animator.getStartDelay();
7974c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                animator.setStartDelay(delay);
7984c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            }
7994c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        }
800c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
801c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
802c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
8034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Internal utility method for checking whether a given view/id
8044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * is valid for this transition, where "valid" means that either
8054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the Transition has no target/targetId list (the default, in which
8064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * cause the transition should act on all views in the hiearchy), or
8074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the given view is in the target list or the view id is in the
8084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * targetId list. If the target parameter is null, then the target list
8094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * is not checked (this is in the case of ListView items, where the
8104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * views are ignored and only the ids are used).
811c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
812756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    boolean isValidTarget(View target) {
813756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        int targetId = target.getId();
814756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetIdExcludes != null && mTargetIdExcludes.contains(targetId)) {
8154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return false;
8164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
8174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mTargetExcludes != null && mTargetExcludes.contains(target)) {
8184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return false;
8194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
820756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetTypeExcludes != null) {
8214e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            int numTypes = mTargetTypeExcludes.size();
8224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            for (int i = 0; i < numTypes; ++i) {
8234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                Class type = mTargetTypeExcludes.get(i);
8244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                if (type.isInstance(target)) {
8254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    return false;
8264e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
8274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
8284e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
829756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetNameExcludes != null && ViewCompat.getTransitionName(target) != null) {
830756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (mTargetNameExcludes.contains(ViewCompat.getTransitionName(target))) {
831756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                return false;
832756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
833756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
834756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetIds.size() == 0 && mTargets.size() == 0
835756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                && (mTargetTypes == null || mTargetTypes.isEmpty())
836756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                && (mTargetNames == null || mTargetNames.isEmpty())) {
8374e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return true;
8384e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
839756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetIds.contains(targetId) || mTargets.contains(target)) {
840756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            return true;
8414e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
842756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetNames != null && mTargetNames.contains(ViewCompat.getTransitionName(target))) {
843756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            return true;
844756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
845756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetTypes != null) {
846756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            for (int i = 0; i < mTargetTypes.size(); ++i) {
847756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (mTargetTypes.get(i).isInstance(target)) {
8484e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    return true;
8494e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
8504e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
8514e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
8524e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return false;
8534e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
8544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
8554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
8564e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        ArrayMap<Animator, AnimationInfo> runningAnimators = sRunningAnimators.get();
8574e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (runningAnimators == null) {
8584e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            runningAnimators = new ArrayMap<>();
8594e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            sRunningAnimators.set(runningAnimators);
8604e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
8614e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return runningAnimators;
862c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
863c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
864c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
8654e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * This is called internally once all animations have been set up by the
8664e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * transition hierarchy. \
867c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
8684e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @hide
8694e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
8704e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @RestrictTo(LIBRARY_GROUP)
8714e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    protected void runAnimators() {
8724e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (DBG) {
8734e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            Log.d(LOG_TAG, "runAnimators() on " + this);
8744e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
8754e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        start();
8764e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
8774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        // Now start every Animator that was previously created for this transition
8784e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        for (Animator anim : mAnimators) {
8794e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (DBG) {
8804e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                Log.d(LOG_TAG, "  anim: " + anim);
8814e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
8824e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (runningAnimators.containsKey(anim)) {
8834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                start();
8844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                runAnimator(anim, runningAnimators);
8854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
8864e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
8874e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mAnimators.clear();
8884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        end();
8894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
8904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
8914e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private void runAnimator(Animator animator,
8924e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            final ArrayMap<Animator, AnimationInfo> runningAnimators) {
8934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (animator != null) {
8944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            // TODO: could be a single listener instance for all of them since it uses the param
8954e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            animator.addListener(new AnimatorListenerAdapter() {
8964e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                @Override
8974e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                public void onAnimationStart(Animator animation) {
8984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    mCurrentAnimators.add(animation);
8994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
9004e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
9014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                @Override
9024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                public void onAnimationEnd(Animator animation) {
9034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    runningAnimators.remove(animation);
9044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    mCurrentAnimators.remove(animation);
9054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
9064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            });
9074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            animate(animator);
9084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
9094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
9104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
9114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
9124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Captures the values in the start scene for the properties that this
9134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * transition monitors. These values are then passed as the startValues
9144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * structure in a later call to
9154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
9164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * The main concern for an implementation is what the
9174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * properties are that the transition cares about and what the values are
9184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * for all of those properties. The start and end values will be compared
9194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * later during the
9204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}
9214e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * method to determine what, if any, animations, should be run.
922c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
9234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <p>Subclasses must implement this method. The method should only be called by the
9244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * transition system; it is not intended to be called from external classes.</p>
9254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
9264e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param transitionValues The holder for any values that the Transition
9274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         wishes to store. Values are stored in the <code>values</code> field
9284e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         of this TransitionValues object and are keyed from
9294e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         a String value. For example, to store a view's rotation value,
9304e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         a transition might call
9314e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         <code>transitionValues.values.put("appname:transitionname:rotation",
9324e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         view.getRotation())</code>. The target view will already be stored
9334e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         in
9344e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         the transitionValues structure when this method is called.
9354e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #captureEndValues(TransitionValues)
9364e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
9374e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
9384e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public abstract void captureStartValues(@NonNull TransitionValues transitionValues);
9394e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
9404e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
9414e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Captures the values in the end scene for the properties that this
9424e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * transition monitors. These values are then passed as the endValues
9434e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * structure in a later call to
9444e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}.
9454e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * The main concern for an implementation is what the
9464e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * properties are that the transition cares about and what the values are
9474e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * for all of those properties. The start and end values will be compared
9484e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * later during the
9494e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * {@link #createAnimator(ViewGroup, TransitionValues, TransitionValues)}
9504e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * method to determine what, if any, animations, should be run.
9514e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
9524e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <p>Subclasses must implement this method. The method should only be called by the
9534e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * transition system; it is not intended to be called from external classes.</p>
9544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
9554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param transitionValues The holder for any values that the Transition
9564e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         wishes to store. Values are stored in the <code>values</code> field
9574e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         of this TransitionValues object and are keyed from
9584e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         a String value. For example, to store a view's rotation value,
9594e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         a transition might call
9604e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         <code>transitionValues.values.put("appname:transitionname:rotation",
9614e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         view.getRotation())</code>. The target view will already be stored
9624e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         in
9634e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                         the transitionValues structure when this method is called.
9644e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #captureStartValues(TransitionValues)
9654e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #createAnimator(ViewGroup, TransitionValues, TransitionValues)
9664e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
9674e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public abstract void captureEndValues(@NonNull TransitionValues transitionValues);
9684e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
9694e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
9704e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Sets the target view instances that this Transition is interested in
9714e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * animating. By default, there are no targets, and a Transition will
9724e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * listen for changes on every view in the hierarchy below the sceneRoot
9734e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * of the Scene being transitioned into. Setting targets constrains
9744e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the Transition to only listen for, and act on, these views.
9754e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * All other views will be ignored.
9764e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
9774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <p>The target list is like the {@link #addTarget(int) targetId}
9784e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * list except this list specifies the actual View instances, not the ids
9794e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * of the views. This is an important distinction when scene changes involve
9804e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * view hierarchies which have been inflated separately; different views may
9814e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * share the same id but not actually be the same instance. If the transition
9824e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * should treat those views as the same, then {@link #addTarget(int)} should be used
9834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * instead of {@link #addTarget(View)}. If, on the other hand, scene changes involve
9844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * changes all within the same view hierarchy, among views which do not
9854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * necessarily have ids set on them, then the target list of views may be more
9864e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * convenient.</p>
9874e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
9884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param target A View on which the Transition will act, must be non-null.
9894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return The Transition to which the target is added.
9904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Returning the same object makes it easier to chain calls during
9914e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * construction, such as
9924e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <code>transitionSet.addTransitions(new Fade()).addTarget(someView);</code>
9934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #addTarget(int)
994c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
995cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @NonNull
9964e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition addTarget(@NonNull View target) {
9974e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mTargets.add(target);
9984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return this;
9994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
10004e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
10014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
10024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Adds the id of a target view that this Transition is interested in
10034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * animating. By default, there are no targetIds, and a Transition will
10044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * listen for changes on every view in the hierarchy below the sceneRoot
10054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * of the Scene being transitioned into. Setting targetIds constrains
10064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the Transition to only listen for, and act on, views with these IDs.
10074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Views with different IDs, or no IDs whatsoever, will be ignored.
10084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
10094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <p>Note that using ids to specify targets implies that ids should be unique
10104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * within the view hierarchy underneath the scene root.</p>
10114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
10124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param targetId The id of a target view, must be a positive number.
10134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return The Transition to which the targetId is added.
10144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Returning the same object makes it easier to chain calls during
10154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * construction, such as
10164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <code>transitionSet.addTransitions(new Fade()).addTarget(someId);</code>
10174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see View#getId()
10184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
10194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @NonNull
10204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition addTarget(@IdRes int targetId) {
1021fa7b4e1c1d73d96dc7bd45ec798c0382a1bdd3efTor Norbye        if (targetId != 0) {
10224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mTargetIds.add(targetId);
10234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
10244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return this;
10254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
10264e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
10274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
1028756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Adds the transitionName of a target view that this Transition is interested in
1029756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * animating. By default, there are no targetNames, and a Transition will
1030756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * listen for changes on every view in the hierarchy below the sceneRoot
1031756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * of the Scene being transitioned into. Setting targetNames constrains
1032756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * the Transition to only listen for, and act on, views with these transitionNames.
1033756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Views with different transitionNames, or no transitionName whatsoever, will be ignored.
1034756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
1035756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * <p>Note that transitionNames should be unique within the view hierarchy.</p>
1036756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
1037756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @param targetName The transitionName of a target view, must be non-null.
1038756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @return The Transition to which the target transitionName is added.
1039756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Returning the same object makes it easier to chain calls during
1040756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * construction, such as
1041756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * <code>transitionSet.addTransitions(new Fade()).addTarget(someName);</code>
1042756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @see ViewCompat#getTransitionName(View)
1043756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
1044756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @NonNull
1045756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public Transition addTarget(@NonNull String targetName) {
1046756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetNames == null) {
1047756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            mTargetNames = new ArrayList<>();
1048756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1049756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        mTargetNames.add(targetName);
1050756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return this;
1051756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1052756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1053756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
1054756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Adds the Class of a target view that this Transition is interested in
1055756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * animating. By default, there are no targetTypes, and a Transition will
1056756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * listen for changes on every view in the hierarchy below the sceneRoot
1057756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * of the Scene being transitioned into. Setting targetTypes constrains
1058756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * the Transition to only listen for, and act on, views with these classes.
1059756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Views with different classes will be ignored.
1060756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
1061756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * <p>Note that any View that can be cast to targetType will be included, so
1062756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * if targetType is <code>View.class</code>, all Views will be included.</p>
1063756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
1064756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @param targetType The type to include when running this transition.
1065756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @return The Transition to which the target class was added.
1066756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Returning the same object makes it easier to chain calls during
1067756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * construction, such as
1068756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * <code>transitionSet.addTransitions(new Fade()).addTarget(ImageView.class);</code>
1069756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @see #addTarget(int)
1070756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @see #addTarget(android.view.View)
1071756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @see #excludeTarget(Class, boolean)
1072756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @see #excludeChildren(Class, boolean)
1073756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
1074756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @NonNull
1075756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public Transition addTarget(@NonNull Class targetType) {
1076756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetTypes == null) {
1077756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            mTargetTypes = new ArrayList<>();
1078756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1079756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        mTargetTypes.add(targetType);
1080756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return this;
1081756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1082756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1083756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
10844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Removes the given target from the list of targets that this Transition
10854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * is interested in animating.
10864e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
10874e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param target The target view, must be non-null.
10884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return Transition The Transition from which the target is removed.
10894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Returning the same object makes it easier to chain calls during
10904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * construction, such as
10914e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <code>transitionSet.addTransitions(new Fade()).removeTarget(someView);</code>
10924e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
10934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @NonNull
10944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition removeTarget(@NonNull View target) {
10954e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mTargets.remove(target);
10964e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return this;
10974e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
10984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
10994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
11004e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Removes the given targetId from the list of ids that this Transition
11014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * is interested in animating.
11024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
11034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param targetId The id of a target view, must be a positive number.
11044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return The Transition from which the targetId is removed.
11054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Returning the same object makes it easier to chain calls during
11064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * construction, such as
11074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <code>transitionSet.addTransitions(new Fade()).removeTargetId(someId);</code>
11084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
11094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @NonNull
11104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition removeTarget(@IdRes int targetId) {
1111fa7b4e1c1d73d96dc7bd45ec798c0382a1bdd3efTor Norbye        if (targetId != 0) {
11124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mTargetIds.remove((Integer) targetId);
11134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1114c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return this;
1115c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1116c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1117c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
1118756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Removes the given targetName from the list of transitionNames that this Transition
1119756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * is interested in animating.
1120756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
1121756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @param targetName The transitionName of a target view, must not be null.
1122756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @return The Transition from which the targetName is removed.
1123756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Returning the same object makes it easier to chain calls during
1124756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * construction, such as
1125756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * <code>transitionSet.addTransitions(new Fade()).removeTargetName(someName);</code>
1126756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
1127756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @NonNull
1128756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public Transition removeTarget(@NonNull String targetName) {
1129756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetNames != null) {
1130756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            mTargetNames.remove(targetName);
1131756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1132756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return this;
1133756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1134756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1135756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
1136756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Removes the given target from the list of targets that this Transition
1137756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * is interested in animating.
1138756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
1139756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @param target The type of the target view, must be non-null.
1140756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @return Transition The Transition from which the target is removed.
1141756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Returning the same object makes it easier to chain calls during
1142756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * construction, such as
1143756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * <code>transitionSet.addTransitions(new Fade()).removeTarget(someType);</code>
1144756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
1145756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @NonNull
1146756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public Transition removeTarget(@NonNull Class target) {
1147756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetTypes != null) {
1148756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            mTargetTypes.remove(target);
1149756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1150756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return this;
1151756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1152756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1153756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
1154756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Utility method to manage the boilerplate code that is the same whether we
1155756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * are excluding targets or their children.
1156756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
1157756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private static <T> ArrayList<T> excludeObject(ArrayList<T> list, T target, boolean exclude) {
1158756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (target != null) {
1159756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (exclude) {
1160756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                list = ArrayListManager.add(list, target);
1161756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            } else {
1162756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                list = ArrayListManager.remove(list, target);
1163756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
1164756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1165756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return list;
1166756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1167756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1168756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
1169c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Whether to add the given target to the list of targets to exclude from this
1170c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * transition. The <code>exclude</code> parameter specifies whether the target
1171c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * should be added to or removed from the excluded list.
1172c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
1173c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1174c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * a view hierarchy while skipping target views that should not be part of
1175c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * the transition. For example, you may want to avoid animating children
1176c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * of a specific ListView or Spinner. Views can be excluded either by their
1177c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * id, or by their instance reference, or by the Class of that view
1178c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * (eg, {@link Spinner}).</p>
1179c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
1180c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param target  The target to ignore when running this transition.
1181c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param exclude Whether to add the target to or remove the target from the
1182c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *                current list of excluded targets.
1183c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @return This transition object.
1184c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #excludeChildren(View, boolean)
1185c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #excludeTarget(int, boolean)
1186c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #excludeTarget(Class, boolean)
1187c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
1188cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @NonNull
1189cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    public Transition excludeTarget(@NonNull View target, boolean exclude) {
11904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mTargetExcludes = excludeView(mTargetExcludes, target, exclude);
1191c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return this;
1192c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1193c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1194c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
1195c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Whether to add the given id to the list of target ids to exclude from this
1196c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * transition. The <code>exclude</code> parameter specifies whether the target
1197c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * should be added to or removed from the excluded list.
1198c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
1199c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1200c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * a view hierarchy while skipping target views that should not be part of
1201c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * the transition. For example, you may want to avoid animating children
1202c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * of a specific ListView or Spinner. Views can be excluded either by their
1203c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * id, or by their instance reference, or by the Class of that view
1204c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * (eg, {@link Spinner}).</p>
1205c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
1206c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param targetId The id of a target to ignore when running this transition.
1207c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param exclude  Whether to add the target to or remove the target from the
1208c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *                 current list of excluded targets.
1209c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @return This transition object.
1210c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #excludeChildren(int, boolean)
1211c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #excludeTarget(View, boolean)
1212c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #excludeTarget(Class, boolean)
1213c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
1214cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @NonNull
1215c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public Transition excludeTarget(@IdRes int targetId, boolean exclude) {
12164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mTargetIdExcludes = excludeId(mTargetIdExcludes, targetId, exclude);
12174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return this;
12184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
12194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
12204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
1221756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Whether to add the given transitionName to the list of target transitionNames to exclude
1222756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * from this transition. The <code>exclude</code> parameter specifies whether the target
1223756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * should be added to or removed from the excluded list.
1224756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
1225756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1226756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * a view hierarchy while skipping target views that should not be part of
1227756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * the transition. For example, you may want to avoid animating children
1228756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * of a specific ListView or Spinner. Views can be excluded by their
1229756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * id, their instance reference, their transitionName, or by the Class of that view
1230756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * (eg, {@link Spinner}).</p>
1231756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
1232a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @param targetName The name of a target to ignore when running this transition.
1233a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @param exclude    Whether to add the target to or remove the target from the
1234a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     *                   current list of excluded targets.
1235a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @return This transition object.
1236756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @see #excludeTarget(View, boolean)
1237756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @see #excludeTarget(int, boolean)
1238756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @see #excludeTarget(Class, boolean)
1239756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
1240756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @NonNull
1241756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public Transition excludeTarget(@NonNull String targetName, boolean exclude) {
1242756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        mTargetNameExcludes = excludeObject(mTargetNameExcludes, targetName, exclude);
1243756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return this;
1244756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1245756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1246756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
12474e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Whether to add the children of given target to the list of target children
12484e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * to exclude from this transition. The <code>exclude</code> parameter specifies
12494e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * whether the target should be added to or removed from the excluded list.
12504e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
12514e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <p>Excluding targets is a general mechanism for allowing transitions to run on
12524e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * a view hierarchy while skipping target views that should not be part of
12534e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the transition. For example, you may want to avoid animating children
12544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * of a specific ListView or Spinner. Views can be excluded either by their
12554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * id, or by their instance reference, or by the Class of that view
12564e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * (eg, {@link Spinner}).</p>
12574e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
12584e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param target  The target to ignore when running this transition.
12594e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param exclude Whether to add the target to or remove the target from the
12604e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                current list of excluded targets.
12614e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return This transition object.
12624e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #excludeTarget(View, boolean)
12634e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #excludeChildren(int, boolean)
12644e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #excludeChildren(Class, boolean)
12654e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
12664e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @NonNull
12674e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition excludeChildren(@NonNull View target, boolean exclude) {
12684e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mTargetChildExcludes = excludeView(mTargetChildExcludes, target, exclude);
1269c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return this;
1270c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1271c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1272c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
12734e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Whether to add the children of the given id to the list of targets to exclude
12744e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * from this transition. The <code>exclude</code> parameter specifies whether
12754e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the children of the target should be added to or removed from the excluded list.
12764e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Excluding children in this way provides a simple mechanism for excluding all
12774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * children of specific targets, rather than individually excluding each
12784e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * child individually.
12794e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
12804e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <p>Excluding targets is a general mechanism for allowing transitions to run on
12814e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * a view hierarchy while skipping target views that should not be part of
12824e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the transition. For example, you may want to avoid animating children
12834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * of a specific ListView or Spinner. Views can be excluded either by their
12844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * id, or by their instance reference, or by the Class of that view
12854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * (eg, {@link Spinner}).</p>
12864e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
12874e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param targetId The id of a target whose children should be ignored when running
12884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                 this transition.
12894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param exclude  Whether to add the target to or remove the target from the
12904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                 current list of excluded-child targets.
12914e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return This transition object.
12924e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #excludeTarget(int, boolean)
12934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #excludeChildren(View, boolean)
12944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #excludeChildren(Class, boolean)
12954e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
12964e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @NonNull
12974e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition excludeChildren(@IdRes int targetId, boolean exclude) {
12984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mTargetIdChildExcludes = excludeId(mTargetIdChildExcludes, targetId, exclude);
12994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return this;
13004e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
13014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
13024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
13034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Utility method to manage the boilerplate code that is the same whether we
13044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * are excluding targets or their children.
13054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
13064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<Integer> excludeId(ArrayList<Integer> list, int targetId, boolean exclude) {
13074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (targetId > 0) {
13084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (exclude) {
13094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                list = ArrayListManager.add(list, targetId);
13104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            } else {
13114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                list = ArrayListManager.remove(list, targetId);
13124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
13134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
13144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return list;
13154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
13164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
13174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
13184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Utility method to manage the boilerplate code that is the same whether we
13194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * are excluding targets or their children.
13204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
13214e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<View> excludeView(ArrayList<View> list, View target, boolean exclude) {
13224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (target != null) {
13234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (exclude) {
13244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                list = ArrayListManager.add(list, target);
13254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            } else {
13264e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                list = ArrayListManager.remove(list, target);
13274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
13284e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
13294e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return list;
13304e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
13314e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
13324e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
1333c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Whether to add the given type to the list of types to exclude from this
1334c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * transition. The <code>exclude</code> parameter specifies whether the target
1335c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * type should be added to or removed from the excluded list.
1336c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
1337c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>Excluding targets is a general mechanism for allowing transitions to run on
1338c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * a view hierarchy while skipping target views that should not be part of
1339c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * the transition. For example, you may want to avoid animating children
1340c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * of a specific ListView or Spinner. Views can be excluded either by their
1341c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * id, or by their instance reference, or by the Class of that view
1342c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * (eg, {@link Spinner}).</p>
1343c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
1344c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param type    The type to ignore when running this transition.
1345c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param exclude Whether to add the target type to or remove it from the
1346c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *                current list of excluded target types.
1347c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @return This transition object.
1348c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #excludeChildren(Class, boolean)
1349c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #excludeTarget(int, boolean)
1350c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #excludeTarget(View, boolean)
1351c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
1352cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @NonNull
1353cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    public Transition excludeTarget(@NonNull Class type, boolean exclude) {
13544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mTargetTypeExcludes = excludeType(mTargetTypeExcludes, type, exclude);
1355c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return this;
1356c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1357c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1358c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
13594e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Whether to add the given type to the list of types whose children should
13604e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * be excluded from this transition. The <code>exclude</code> parameter
13614e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * specifies whether the target type should be added to or removed from
13624e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the excluded list.
1363c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
13644e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <p>Excluding targets is a general mechanism for allowing transitions to run on
13654e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * a view hierarchy while skipping target views that should not be part of
13664e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * the transition. For example, you may want to avoid animating children
13674e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * of a specific ListView or Spinner. Views can be excluded either by their
13684e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * id, or by their instance reference, or by the Class of that view
13694e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * (eg, {@link Spinner}).</p>
13704e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
13714e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param type    The type to ignore when running this transition.
13724e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param exclude Whether to add the target type to or remove it from the
13734e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                current list of excluded target types.
13744e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return This transition object.
13754e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #excludeTarget(Class, boolean)
13764e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #excludeChildren(int, boolean)
13774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @see #excludeChildren(View, boolean)
13784e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
13794e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @NonNull
13804e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition excludeChildren(@NonNull Class type, boolean exclude) {
13814e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mTargetTypeChildExcludes = excludeType(mTargetTypeChildExcludes, type, exclude);
13824e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return this;
13834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
13844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
13854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
13864e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Utility method to manage the boilerplate code that is the same whether we
13874e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * are excluding targets or their children.
13884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
13894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private ArrayList<Class> excludeType(ArrayList<Class> list, Class type, boolean exclude) {
13904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (type != null) {
13914e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (exclude) {
13924e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                list = ArrayListManager.add(list, type);
13934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            } else {
13944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                list = ArrayListManager.remove(list, type);
13954e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
13964e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
13974e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return list;
13984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
13994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
14004e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
14014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Returns the array of target IDs that this transition limits itself to
14024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * tracking and animating. If the array is null for both this method and
14034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * {@link #getTargets()}, then this transition is
14044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * not limited to specific views, and will handle changes to any views
14054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * in the hierarchy of a scene change.
14064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
14074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return the list of target IDs
14084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
14094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @NonNull
14104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public List<Integer> getTargetIds() {
14114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return mTargetIds;
14124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
14134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
14144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
14154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Returns the array of target views that this transition limits itself to
14164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * tracking and animating. If the array is null for both this method and
14174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * {@link #getTargetIds()}, then this transition is
14184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * not limited to specific views, and will handle changes to any views
14194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * in the hierarchy of a scene change.
14204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
14214e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return the list of target views
14224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
14234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @NonNull
14244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public List<View> getTargets() {
14254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return mTargets;
14264e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
14274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
14284e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
1429756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Returns the list of target transitionNames that this transition limits itself to
1430756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * tracking and animating. If the list is null or empty for
1431756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
1432756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * {@link #getTargetTypes()} then this transition is
1433756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * not limited to specific views, and will handle changes to any views
1434756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * in the hierarchy of a scene change.
1435756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
1436756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @return the list of target transitionNames
1437756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
1438756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @Nullable
1439756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public List<String> getTargetNames() {
1440756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return mTargetNames;
1441756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1442756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1443756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
1444756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Returns the list of target transitionNames that this transition limits itself to
1445756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * tracking and animating. If the list is null or empty for
1446756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
1447756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * {@link #getTargetTypes()} then this transition is
1448756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * not limited to specific views, and will handle changes to any views
1449756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * in the hierarchy of a scene change.
1450756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
1451756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @return the list of target Types
1452756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
1453756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @Nullable
1454756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    public List<Class> getTargetTypes() {
1455756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return mTargetTypes;
1456756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1457756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1458756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
14594e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Recursive method that captures values for the given view and the
14604e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * hierarchy underneath it.
14614e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
14624e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param sceneRoot The root of the view hierarchy being captured
14634e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param start     true if this capture is happening before the scene change,
14644e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                  false otherwise
14654e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
14664e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    void captureValues(ViewGroup sceneRoot, boolean start) {
14674e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        clearValues(start);
1468756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if ((mTargetIds.size() > 0 || mTargets.size() > 0)
1469756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                && (mTargetNames == null || mTargetNames.isEmpty())
1470756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                && (mTargetTypes == null || mTargetTypes.isEmpty())) {
1471756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            for (int i = 0; i < mTargetIds.size(); ++i) {
1472756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                int id = mTargetIds.get(i);
1473756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                View view = sceneRoot.findViewById(id);
1474756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (view != null) {
1475756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    TransitionValues values = new TransitionValues();
1476756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    values.view = view;
1477756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    if (start) {
1478756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        captureStartValues(values);
1479756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    } else {
1480756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        captureEndValues(values);
1481756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    }
1482756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    values.mTargetedTransitions.add(this);
14834c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                    capturePropagationValues(values);
1484756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    if (start) {
1485756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        addViewValues(mStartValues, view, values);
1486756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    } else {
1487756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        addViewValues(mEndValues, view, values);
14884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
14894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
14904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
1491756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            for (int i = 0; i < mTargets.size(); ++i) {
1492756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                View view = mTargets.get(i);
1493756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                TransitionValues values = new TransitionValues();
1494756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                values.view = view;
1495756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (start) {
1496756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    captureStartValues(values);
1497756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                } else {
1498756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    captureEndValues(values);
1499756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                }
1500756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                values.mTargetedTransitions.add(this);
15014c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                capturePropagationValues(values);
1502756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (start) {
1503756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    addViewValues(mStartValues, view, values);
1504756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                } else {
1505756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    addViewValues(mEndValues, view, values);
15064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
15074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
15084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        } else {
15094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            captureHierarchy(sceneRoot, start);
15104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1511756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (!start && mNameOverrides != null) {
1512756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            int numOverrides = mNameOverrides.size();
1513756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            ArrayList<View> overriddenViews = new ArrayList<>(numOverrides);
1514756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            for (int i = 0; i < numOverrides; i++) {
1515756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                String fromName = mNameOverrides.keyAt(i);
1516756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                overriddenViews.add(mStartValues.mNameValues.remove(fromName));
1517756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
1518756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            for (int i = 0; i < numOverrides; i++) {
1519756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                View view = overriddenViews.get(i);
1520756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (view != null) {
1521756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    String toName = mNameOverrides.valueAt(i);
1522756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    mStartValues.mNameValues.put(toName, view);
1523756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                }
1524756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
1525756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1526756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1527756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1528756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private static void addViewValues(TransitionValuesMaps transitionValuesMaps,
1529756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            View view, TransitionValues transitionValues) {
1530756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        transitionValuesMaps.mViewValues.put(view, transitionValues);
1531756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        int id = view.getId();
1532756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (id >= 0) {
1533756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (transitionValuesMaps.mIdValues.indexOfKey(id) >= 0) {
1534756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                // Duplicate IDs cannot match by ID.
1535756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                transitionValuesMaps.mIdValues.put(id, null);
1536756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            } else {
1537756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                transitionValuesMaps.mIdValues.put(id, view);
1538756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
1539756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1540756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        String name = ViewCompat.getTransitionName(view);
1541756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (name != null) {
1542756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (transitionValuesMaps.mNameValues.containsKey(name)) {
1543756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                // Duplicate transitionNames: cannot match by transitionName.
1544756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                transitionValuesMaps.mNameValues.put(name, null);
1545756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            } else {
1546756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                transitionValuesMaps.mNameValues.put(name, view);
1547756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
1548756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1549756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (view.getParent() instanceof ListView) {
1550756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            ListView listview = (ListView) view.getParent();
1551756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (listview.getAdapter().hasStableIds()) {
1552756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                int position = listview.getPositionForView(view);
1553756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                long itemId = listview.getItemIdAtPosition(position);
1554756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (transitionValuesMaps.mItemIdValues.indexOfKey(itemId) >= 0) {
1555756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    // Duplicate item IDs: cannot match by item ID.
1556756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    View alreadyMatched = transitionValuesMaps.mItemIdValues.get(itemId);
1557756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    if (alreadyMatched != null) {
1558756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        ViewCompat.setHasTransientState(alreadyMatched, false);
1559756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        transitionValuesMaps.mItemIdValues.put(itemId, null);
1560756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    }
1561756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                } else {
1562756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    ViewCompat.setHasTransientState(view, true);
1563756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    transitionValuesMaps.mItemIdValues.put(itemId, view);
1564756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                }
1565756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
1566756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
15674e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
15684e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
15694e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
15704e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Clear valuesMaps for specified start/end state
15714e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
15724e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param start true if the start values should be cleared, false otherwise
1573c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
15744e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    void clearValues(boolean start) {
15754e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (start) {
15764e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mStartValues.mViewValues.clear();
15774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mStartValues.mIdValues.clear();
15784e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mStartValues.mItemIdValues.clear();
15794e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        } else {
15804e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mEndValues.mViewValues.clear();
15814e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mEndValues.mIdValues.clear();
15824e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mEndValues.mItemIdValues.clear();
15834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1584c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1585c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1586c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
15874e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Recursive method which captures values for an entire view hierarchy,
15884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * starting at some root view. Transitions without targetIDs will use this
15894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * method to capture values for all possible views.
1590c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
15914e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param view  The view for which to capture values. Children of this View
15924e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *              will also be captured, recursively down to the leaf nodes.
15934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param start true if values are being captured in the start scene, false
15944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *              otherwise.
1595c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
15964e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private void captureHierarchy(View view, boolean start) {
15974e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (view == null) {
15984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return;
15994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1600756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        int id = view.getId();
16014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mTargetIdExcludes != null && mTargetIdExcludes.contains(id)) {
16024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return;
16034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
16044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mTargetExcludes != null && mTargetExcludes.contains(view)) {
16054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return;
16064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1607756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mTargetTypeExcludes != null) {
16084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            int numTypes = mTargetTypeExcludes.size();
16094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            for (int i = 0; i < numTypes; ++i) {
16104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                if (mTargetTypeExcludes.get(i).isInstance(view)) {
16114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    return;
16124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
16134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
16144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1615756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (view.getParent() instanceof ViewGroup) {
1616756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            TransitionValues values = new TransitionValues();
1617756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            values.view = view;
1618756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (start) {
1619756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                captureStartValues(values);
16204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            } else {
1621756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                captureEndValues(values);
16224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
1623756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            values.mTargetedTransitions.add(this);
16244c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            capturePropagationValues(values);
1625756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (start) {
1626756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                addViewValues(mStartValues, view, values);
16274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            } else {
1628756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                addViewValues(mEndValues, view, values);
16294e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
16304e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
16314e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (view instanceof ViewGroup) {
16324e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            // Don't traverse child hierarchy if there are any child-excludes on this view
16334e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (mTargetIdChildExcludes != null && mTargetIdChildExcludes.contains(id)) {
16344e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                return;
16354e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
16364e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (mTargetChildExcludes != null && mTargetChildExcludes.contains(view)) {
16374e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                return;
16384e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
1639756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (mTargetTypeChildExcludes != null) {
16404e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                int numTypes = mTargetTypeChildExcludes.size();
16414e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                for (int i = 0; i < numTypes; ++i) {
16424e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    if (mTargetTypeChildExcludes.get(i).isInstance(view)) {
16434e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        return;
16444e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
16454e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
16464e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
16474e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            ViewGroup parent = (ViewGroup) view;
16484e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            for (int i = 0; i < parent.getChildCount(); ++i) {
16494e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                captureHierarchy(parent.getChildAt(i), start);
16504e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
16514e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1652c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1653c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1654c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
16554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * This method can be called by transitions to get the TransitionValues for
16564e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * any particular view during the transition-playing process. This might be
16574e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * necessary, for example, to query the before/after state of related views
16584e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * for a given transition.
1659c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
1660cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @Nullable
16614e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public TransitionValues getTransitionValues(@NonNull View view, boolean start) {
16624e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mParent != null) {
16634e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return mParent.getTransitionValues(view, start);
16644e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
16654e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        TransitionValuesMaps valuesMaps = start ? mStartValues : mEndValues;
1666756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return valuesMaps.mViewValues.get(view);
1667756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1668756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1669756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    /**
1670756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * Find the matched start or end value for a given View. This is only valid
1671756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * after playTransition starts. For example, it will be valid in
1672756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}, but not
1673756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * in {@link #captureStartValues(TransitionValues)}.
1674756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     *
1675756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @param view        The view to find the match for.
1676756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @param viewInStart Is View from the start values or end values.
1677756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * @return The matching TransitionValues for view in either start or end values, depending
1678756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     * on viewInStart or null if there is no match for the given view.
1679756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki     */
1680756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    TransitionValues getMatchedTransitionValues(View view, boolean viewInStart) {
1681756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (mParent != null) {
1682756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            return mParent.getMatchedTransitionValues(view, viewInStart);
1683756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1684756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        ArrayList<TransitionValues> lookIn = viewInStart ? mStartValuesList : mEndValuesList;
1685756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (lookIn == null) {
1686756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            return null;
1687756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1688756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        int count = lookIn.size();
1689756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        int index = -1;
1690756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        for (int i = 0; i < count; i++) {
1691756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            TransitionValues values = lookIn.get(i);
1692756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (values == null) {
1693756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                return null;
16944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
1695756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (values.view == view) {
1696756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                index = i;
1697756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                break;
16984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
1699756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1700756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        TransitionValues values = null;
1701756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (index >= 0) {
1702756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            ArrayList<TransitionValues> matchIn = viewInStart ? mEndValuesList : mStartValuesList;
1703756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            values = matchIn.get(index);
17044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
17054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return values;
1706c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1707c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1708c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
17094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Pauses this transition, sending out calls to {@link
17104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * TransitionListener#onTransitionPause(Transition)} to all listeners
17114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * and pausing all running animators started by this transition.
1712c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
17134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @hide
1714c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
17154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @RestrictTo(LIBRARY_GROUP)
17164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public void pause(View sceneRoot) {
17174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (!mEnded) {
17184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
17194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            int numOldAnims = runningAnimators.size();
17204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            WindowIdImpl windowId = ViewUtils.getWindowId(sceneRoot);
17214e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            for (int i = numOldAnims - 1; i >= 0; i--) {
17224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                AnimationInfo info = runningAnimators.valueAt(i);
17234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                if (info.mView != null && windowId.equals(info.mWindowId)) {
17244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    Animator anim = runningAnimators.keyAt(i);
1725928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki                    AnimatorUtils.pause(anim);
17264e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
17274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
17284e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (mListeners != null && mListeners.size() > 0) {
17294e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                @SuppressWarnings("unchecked") ArrayList<TransitionListener> tmpListeners =
17304e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        (ArrayList<TransitionListener>) mListeners.clone();
17314e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                int numListeners = tmpListeners.size();
17324e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                for (int i = 0; i < numListeners; ++i) {
17334e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    tmpListeners.get(i).onTransitionPause(this);
17344e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
17354e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
17364e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mPaused = true;
17374e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1738c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1739c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1740c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
17414e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Resumes this transition, sending out calls to {@link
17424e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * TransitionListener#onTransitionPause(Transition)} to all listeners
17434e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * and pausing all running animators started by this transition.
1744c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
17454e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @hide
1746c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
17474e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @RestrictTo(LIBRARY_GROUP)
17484e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public void resume(View sceneRoot) {
17494e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mPaused) {
17504e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (!mEnded) {
17514e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
17524e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                int numOldAnims = runningAnimators.size();
17534e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                WindowIdImpl windowId = ViewUtils.getWindowId(sceneRoot);
17544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                for (int i = numOldAnims - 1; i >= 0; i--) {
17554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    AnimationInfo info = runningAnimators.valueAt(i);
17564e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    if (info.mView != null && windowId.equals(info.mWindowId)) {
17574e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        Animator anim = runningAnimators.keyAt(i);
1758928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki                        AnimatorUtils.resume(anim);
17594e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
17604e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
17614e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                if (mListeners != null && mListeners.size() > 0) {
17624e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    @SuppressWarnings("unchecked") ArrayList<TransitionListener> tmpListeners =
17634e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                            (ArrayList<TransitionListener>) mListeners.clone();
17644e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    int numListeners = tmpListeners.size();
17654e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    for (int i = 0; i < numListeners; ++i) {
17664e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        tmpListeners.get(i).onTransitionResume(this);
17674e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
17684e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
17694e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
17704e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mPaused = false;
17714e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1772c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1773c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1774c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
17754e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Called by TransitionManager to play the transition. This calls
17764e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * createAnimators() to set things up and create all of the animations and then
17774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * runAnimations() to actually start the animations.
1778c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
17794e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    void playTransition(ViewGroup sceneRoot) {
1780756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        mStartValuesList = new ArrayList<>();
1781756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        mEndValuesList = new ArrayList<>();
1782756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        matchStartAndEnd(mStartValues, mEndValues);
1783756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
17844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
17854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        int numOldAnims = runningAnimators.size();
1786756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        WindowIdImpl windowId = ViewUtils.getWindowId(sceneRoot);
17874e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        for (int i = numOldAnims - 1; i >= 0; i--) {
17884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            Animator anim = runningAnimators.keyAt(i);
17894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (anim != null) {
17904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                AnimationInfo oldInfo = runningAnimators.get(anim);
1791928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki                if (oldInfo != null && oldInfo.mView != null
1792928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki                        && windowId.equals(oldInfo.mWindowId)) {
17934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    TransitionValues oldValues = oldInfo.mValues;
17944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    View oldView = oldInfo.mView;
1795756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    TransitionValues startValues = getTransitionValues(oldView, true);
1796756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    TransitionValues endValues = getMatchedTransitionValues(oldView, true);
1797756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    boolean cancel = (startValues != null || endValues != null)
1798dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki                            && oldInfo.mTransition.isTransitionRequired(oldValues, endValues);
17994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    if (cancel) {
18004e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        if (anim.isRunning() || anim.isStarted()) {
18014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                            if (DBG) {
18024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                                Log.d(LOG_TAG, "Canceling anim " + anim);
18034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                            }
18044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                            anim.cancel();
18054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        } else {
18064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                            if (DBG) {
18074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                                Log.d(LOG_TAG, "removing anim from info list: " + anim);
18084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                            }
18094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                            runningAnimators.remove(anim);
18104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        }
18114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
18124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
18134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
18144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
18154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
1816756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        createAnimators(sceneRoot, mStartValues, mEndValues, mStartValuesList, mEndValuesList);
18174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        runAnimators();
1818c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1819c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1820dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki    /**
1821dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     * Returns whether or not the transition should create an Animator, based on the values
1822dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     * captured during {@link #captureStartValues(TransitionValues)} and
1823dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     * {@link #captureEndValues(TransitionValues)}. The default implementation compares the
1824dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     * property values returned from {@link #getTransitionProperties()}, or all property values if
1825dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     * {@code getTransitionProperties()} returns null. Subclasses may override this method to
1826dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     * provide logic more specific to the transition implementation.
1827dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     *
1828dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     * @param startValues the values from captureStartValues, This may be {@code null} if the
1829dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     *                    View did not exist in the start state.
1830dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     * @param endValues   the values from captureEndValues. This may be {@code null} if the View
1831dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     *                    did not exist in the end state.
1832dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki     */
1833dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki    public boolean isTransitionRequired(@Nullable TransitionValues startValues,
1834dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki            @Nullable TransitionValues endValues) {
1835756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        boolean valuesChanged = false;
1836dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki        // if startValues null, then transition didn't care to stash values,
1837756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        // and won't get canceled
1838dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki        if (startValues != null && endValues != null) {
1839756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            String[] properties = getTransitionProperties();
1840756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            if (properties != null) {
1841dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki                for (String property : properties) {
1842dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki                    if (isValueChanged(startValues, endValues, property)) {
1843756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        valuesChanged = true;
1844756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        break;
1845756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    }
1846756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                }
1847756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            } else {
1848dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki                for (String key : startValues.values.keySet()) {
1849dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki                    if (isValueChanged(startValues, endValues, key)) {
1850756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        valuesChanged = true;
1851756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                        break;
1852756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    }
1853756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                }
1854756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            }
1855756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1856756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return valuesChanged;
1857756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1858756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1859756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    private static boolean isValueChanged(TransitionValues oldValues, TransitionValues newValues,
1860756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            String key) {
1861756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        Object oldValue = oldValues.values.get(key);
1862756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        Object newValue = newValues.values.get(key);
1863756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        boolean changed;
1864756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (oldValue == null && newValue == null) {
1865756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            // both are null
1866756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            changed = false;
1867756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        } else if (oldValue == null || newValue == null) {
1868756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            // one is null
1869756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            changed = true;
1870756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        } else {
1871756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            // neither is null
1872756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            changed = !oldValue.equals(newValue);
1873756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1874756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (DBG && changed) {
1875756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            Log.d(LOG_TAG, "Transition.playTransition: "
1876756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    + "oldValue != newValue for " + key
1877756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    + ": old, new = " + oldValue + ", " + newValue);
1878756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
1879756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return changed;
1880756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
1881756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
1882c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
18834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * This is a utility method used by subclasses to handle standard parts of
18844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * setting up and running an Animator: it sets the {@link #getDuration()
18854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * duration} and the {@link #getStartDelay() startDelay}, starts the
18864e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * animation, and, when the animator ends, calls {@link #end()}.
1887c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
18884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param animator The Animator to be run during this transition.
18894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @hide
1890c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
18914e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @RestrictTo(LIBRARY_GROUP)
18924e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    protected void animate(Animator animator) {
18934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        // TODO: maybe pass auto-end as a boolean parameter?
18944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (animator == null) {
18954e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            end();
18964e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        } else {
18974e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (getDuration() >= 0) {
18984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                animator.setDuration(getDuration());
18994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
19004e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (getStartDelay() >= 0) {
19014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                animator.setStartDelay(getStartDelay());
19024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
19034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (getInterpolator() != null) {
19044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                animator.setInterpolator(getInterpolator());
19054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
19064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            animator.addListener(new AnimatorListenerAdapter() {
19074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                @Override
19084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                public void onAnimationEnd(Animator animation) {
19094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    end();
19104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    animation.removeListener(this);
19114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
19124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            });
19134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            animator.start();
19144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1915c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1916c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1917c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
19184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * This method is called automatically by the transition and
19194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * TransitionSet classes prior to a Transition subclass starting;
19204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * subclasses should not need to call it directly.
1921c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
19224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @hide
1923c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
19244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @RestrictTo(LIBRARY_GROUP)
19254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    protected void start() {
19264e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mNumInstances == 0) {
19274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (mListeners != null && mListeners.size() > 0) {
19284e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                @SuppressWarnings("unchecked") ArrayList<TransitionListener> tmpListeners =
19294e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        (ArrayList<TransitionListener>) mListeners.clone();
19304e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                int numListeners = tmpListeners.size();
19314e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                for (int i = 0; i < numListeners; ++i) {
19324e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    tmpListeners.get(i).onTransitionStart(this);
19334e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
19344e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
19354e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mEnded = false;
19364e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
19374e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mNumInstances++;
1938c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1939c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1940c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
19414e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * This method is called automatically by the Transition and
19424e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * TransitionSet classes when a transition finishes, either because
19434e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * a transition did nothing (returned a null Animator from
19444e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * {@link Transition#createAnimator(ViewGroup, TransitionValues,
19454e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * TransitionValues)}) or because the transition returned a valid
19464e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Animator and end() was called in the onAnimationEnd()
19474e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * callback of the AnimatorListener.
1948c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
19494e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @hide
1950c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
19514e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @RestrictTo(LIBRARY_GROUP)
19524e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    protected void end() {
19534e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        --mNumInstances;
19544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mNumInstances == 0) {
19554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (mListeners != null && mListeners.size() > 0) {
19564e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                @SuppressWarnings("unchecked") ArrayList<TransitionListener> tmpListeners =
19574e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        (ArrayList<TransitionListener>) mListeners.clone();
19584e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                int numListeners = tmpListeners.size();
19594e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                for (int i = 0; i < numListeners; ++i) {
19604e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    tmpListeners.get(i).onTransitionEnd(this);
19614e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
19624e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
19634e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            for (int i = 0; i < mStartValues.mItemIdValues.size(); ++i) {
1964756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                View view = mStartValues.mItemIdValues.valueAt(i);
1965756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (view != null) {
1966756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    ViewCompat.setHasTransientState(view, false);
19674e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
19684e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
19694e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            for (int i = 0; i < mEndValues.mItemIdValues.size(); ++i) {
1970756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                View view = mEndValues.mItemIdValues.valueAt(i);
1971756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                if (view != null) {
1972756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                    ViewCompat.setHasTransientState(view, false);
19734e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
19744e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
19754e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mEnded = true;
19764e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1977c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
1978c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1979c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
19804ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki     * Force the transition to move to its end state, ending all the animators.
19814ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki     *
19824ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki     * @hide
19834ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki     */
19844ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki    @RestrictTo(LIBRARY_GROUP)
19854ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki    void forceToEnd(ViewGroup sceneRoot) {
19864ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
19874ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki        int numOldAnims = runningAnimators.size();
19884ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki        if (sceneRoot != null) {
19894ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki            WindowIdImpl windowId = ViewUtils.getWindowId(sceneRoot);
19904ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki            for (int i = numOldAnims - 1; i >= 0; i--) {
19914ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki                AnimationInfo info = runningAnimators.valueAt(i);
19924ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki                if (info.mView != null && windowId != null && windowId.equals(info.mWindowId)) {
19934ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki                    Animator anim = runningAnimators.keyAt(i);
19944ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki                    anim.end();
19954ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki                }
19964ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki            }
19974ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki        }
19984ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki    }
19994ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki
20004ad129858d830ad78de60665fc32d8785e57d541Yuichi Araki    /**
20014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * This method cancels a transition that is currently running.
2002c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
20034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @hide
2004c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
20054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @RestrictTo(LIBRARY_GROUP)
20064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    protected void cancel() {
20074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        int numAnimators = mCurrentAnimators.size();
20084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        for (int i = numAnimators - 1; i >= 0; i--) {
20094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            Animator animator = mCurrentAnimators.get(i);
20104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            animator.cancel();
20114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
20124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mListeners != null && mListeners.size() > 0) {
20134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            @SuppressWarnings("unchecked") ArrayList<TransitionListener> tmpListeners =
20144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    (ArrayList<TransitionListener>) mListeners.clone();
20154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            int numListeners = tmpListeners.size();
20164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            for (int i = 0; i < numListeners; ++i) {
20174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                tmpListeners.get(i).onTransitionCancel(this);
20184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
20194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
2020c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
2021c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
2022c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
20234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Adds a listener to the set of listeners that are sent events through the
20244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * life of an animation, such as start, repeat, and end.
20254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
20264e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @param listener the listener to be added to the current set of listeners
20274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *                 for this animation.
20284e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return This transition object.
2029c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
2030cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @NonNull
20314e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition addListener(@NonNull TransitionListener listener) {
20324e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mListeners == null) {
20334e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mListeners = new ArrayList<>();
20344e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
20354e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mListeners.add(listener);
20364e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return this;
2037c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
2038c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
2039c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
2040c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Removes a listener from the set listening to this animation.
2041c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
2042c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param listener the listener to be removed from the current set of
2043c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *                 listeners for this transition.
2044c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @return This transition object.
2045c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
2046cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @NonNull
2047cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    public Transition removeListener(@NonNull TransitionListener listener) {
20484e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mListeners == null) {
20494e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return this;
20504e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
20514e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mListeners.remove(listener);
20524e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mListeners.size() == 0) {
20534e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mListeners = null;
20544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
2055c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return this;
2056c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
2057c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
2058317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki    /**
2059317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * Sets the algorithm used to calculate two-dimensional interpolation.
2060317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * <p>
2061317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * Transitions such as {@link android.transition.ChangeBounds} move Views, typically
2062317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * in a straight path between the start and end positions. Applications that desire to
2063317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * have these motions move in a curve can change how Views interpolate in two dimensions
2064317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * by extending PathMotion and implementing
2065317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * {@link android.transition.PathMotion#getPath(float, float, float, float)}.
2066317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * </p>
2067317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     *
2068317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * @param pathMotion Algorithm object to use for determining how to interpolate in two
2069317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     *                   dimensions. If null, a straight-path algorithm will be used.
2070317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * @see android.transition.ArcMotion
2071317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * @see PatternPathMotion
2072317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * @see android.transition.PathMotion
2073317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     */
20747f117eb86f61d5f764085a82129600542ba05712Yuichi Araki    public void setPathMotion(@Nullable PathMotion pathMotion) {
2075317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki        if (pathMotion == null) {
2076317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki            mPathMotion = STRAIGHT_PATH_MOTION;
2077317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki        } else {
2078317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki            mPathMotion = pathMotion;
2079317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki        }
2080317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki    }
2081317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki
2082317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki    /**
2083317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * Returns the algorithm object used to interpolate along two dimensions. This is typically
2084317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * used to determine the View motion between two points.
2085317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     *
2086317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * @return The algorithm object used to interpolate along two dimensions.
2087317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * @see android.transition.ArcMotion
2088317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * @see PatternPathMotion
2089317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     * @see android.transition.PathMotion
2090317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki     */
2091642a5dcf3012f0f3012324cffe7cb41b602487c7Yuichi Araki    @NonNull
2092317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki    public PathMotion getPathMotion() {
2093317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki        return mPathMotion;
2094317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki    }
2095317d4bb802dbd80c9ddf1382e037769e58dff919Yuichi Araki
20964c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    /**
20974c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * Sets the callback to use to find the epicenter of a Transition. A null value indicates
20984c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * that there is no epicenter in the Transition and onGetEpicenter() will return null.
20994c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * Transitions like {@link android.transition.Explode} use a point or Rect to orient
21004c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * the direction of travel. This is called the epicenter of the Transition and is
21014c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * typically centered on a touched View. The
21024c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
21034c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * dynamically retrieve the epicenter during a Transition.
21044c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     *
21054c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * @param epicenterCallback The callback to use to find the epicenter of the Transition.
21064c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     */
21074c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    public void setEpicenterCallback(@Nullable EpicenterCallback epicenterCallback) {
21084c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        mEpicenterCallback = epicenterCallback;
21094c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    }
21104c904b38c763179727b9b5ea7a80454630545663Yuichi Araki
21114c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    /**
21124c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * Returns the callback used to find the epicenter of the Transition.
21134c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * Transitions like {@link android.transition.Explode} use a point or Rect to orient
21144c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * the direction of travel. This is called the epicenter of the Transition and is
21154c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * typically centered on a touched View. The
21164c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
21174c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * dynamically retrieve the epicenter during a Transition.
21184c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     *
21194c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * @return the callback used to find the epicenter of the Transition.
21204c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     */
21214c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    @Nullable
21224c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    public EpicenterCallback getEpicenterCallback() {
21234c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        return mEpicenterCallback;
21244c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    }
21254c904b38c763179727b9b5ea7a80454630545663Yuichi Araki
21264c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    /**
21274c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * Returns the epicenter as specified by the
21284c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
21294c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     *
21304c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * @return the epicenter as specified by the
21314c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
21324c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * @see #setEpicenterCallback(EpicenterCallback)
21334c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     */
21344c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    @Nullable
21354c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    public Rect getEpicenter() {
21364c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        if (mEpicenterCallback == null) {
21374c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            return null;
21384c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        }
21394c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        return mEpicenterCallback.onGetEpicenter(this);
21404c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    }
21414c904b38c763179727b9b5ea7a80454630545663Yuichi Araki
21424c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    /**
21434c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * Sets the method for determining Animator start delays.
21444c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * When a Transition affects several Views like {@link android.transition.Explode} or
21454c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
21464c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * such that the Animator start delay depends on position of the View. The
21474c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * TransitionPropagation specifies how the start delays are calculated.
21484c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     *
21494c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * @param transitionPropagation The class used to determine the start delay of
21504c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     *                              Animators created by this Transition. A null value
21514c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     *                              indicates that no delay should be used.
21524c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     */
21537f117eb86f61d5f764085a82129600542ba05712Yuichi Araki    public void setPropagation(@Nullable TransitionPropagation transitionPropagation) {
21544c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        mPropagation = transitionPropagation;
21554c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    }
21564c904b38c763179727b9b5ea7a80454630545663Yuichi Araki
21574c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    /**
21584c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * Returns the {@link android.transition.TransitionPropagation} used to calculate Animator
21594c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * start
21604c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * delays.
21614c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * When a Transition affects several Views like {@link android.transition.Explode} or
21624c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
21634c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * such that the Animator start delay depends on position of the View. The
21644c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * TransitionPropagation specifies how the start delays are calculated.
21654c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     *
21664c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * @return the {@link android.transition.TransitionPropagation} used to calculate Animator start
21674c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * delays. This is null by default.
21684c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     */
21697f117eb86f61d5f764085a82129600542ba05712Yuichi Araki    @Nullable
21704c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    public TransitionPropagation getPropagation() {
21714c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        return mPropagation;
21724c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    }
21734c904b38c763179727b9b5ea7a80454630545663Yuichi Araki
21744c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    /**
21754c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * Captures TransitionPropagation values for the given view and the
21764c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * hierarchy underneath it.
21774c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     */
21784c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    void capturePropagationValues(TransitionValues transitionValues) {
21794c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        if (mPropagation != null && !transitionValues.values.isEmpty()) {
21804c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            String[] propertyNames = mPropagation.getPropagationProperties();
21814c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            if (propertyNames == null) {
21824c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                return;
21834c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            }
21844c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            boolean containsAll = true;
21854c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            for (int i = 0; i < propertyNames.length; i++) {
21864c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                if (!transitionValues.values.containsKey(propertyNames[i])) {
21874c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                    containsAll = false;
21884c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                    break;
21894c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                }
21904c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            }
21914c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            if (!containsAll) {
21924c904b38c763179727b9b5ea7a80454630545663Yuichi Araki                mPropagation.captureValues(transitionValues);
21934c904b38c763179727b9b5ea7a80454630545663Yuichi Araki            }
21944c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        }
21954c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    }
21964c904b38c763179727b9b5ea7a80454630545663Yuichi Araki
21974e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    Transition setSceneRoot(ViewGroup sceneRoot) {
21984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mSceneRoot = sceneRoot;
2199c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return this;
2200c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
2201c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
22024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    void setCanRemoveViews(boolean canRemoveViews) {
22034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mCanRemoveViews = canRemoveViews;
22044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
22054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
22064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @Override
22074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public String toString() {
22084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return toString("");
22094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
22104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
22114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @Override
22124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Transition clone() {
22134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        try {
22144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            Transition clone = (Transition) super.clone();
22154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            clone.mAnimators = new ArrayList<>();
22164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            clone.mStartValues = new TransitionValuesMaps();
22174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            clone.mEndValues = new TransitionValuesMaps();
2218928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki            clone.mStartValuesList = null;
2219928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki            clone.mEndValuesList = null;
22204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return clone;
22214e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        } catch (CloneNotSupportedException e) {
22224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return null;
22234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
22244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
22254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
2226c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
22274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Returns the name of this Transition. This name is used internally to distinguish
22284e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * between different transitions to determine when interrupting transitions overlap.
22294e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * For example, a ChangeBounds running on the same target view as another ChangeBounds
22304e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * should determine whether the old transition is animating to different end values
22314e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * and should be canceled in favor of the new transition.
2232c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
22334e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * <p>By default, a Transition's name is simply the value of {@link Class#getName()},
22344e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * but subclasses are free to override and return something different.</p>
22354e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     *
22364e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * @return The name of this transition.
2237c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
2238cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki    @NonNull
22394e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public String getName() {
22404e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return mName;
2241c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
2242c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
22434e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    String toString(String indent) {
22444e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        String result = indent + getClass().getSimpleName() + "@"
22454e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                + Integer.toHexString(hashCode()) + ": ";
22464e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mDuration != -1) {
22474e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            result += "dur(" + mDuration + ") ";
22484e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
22494e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mStartDelay != -1) {
22504e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            result += "dly(" + mStartDelay + ") ";
22514e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
22524e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mInterpolator != null) {
22534e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            result += "interp(" + mInterpolator + ") ";
22544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
22554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (mTargetIds.size() > 0 || mTargets.size() > 0) {
22564e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            result += "tgts(";
22574e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (mTargetIds.size() > 0) {
22584e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                for (int i = 0; i < mTargetIds.size(); ++i) {
22594e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    if (i > 0) {
22604e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        result += ", ";
22614e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
22624e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    result += mTargetIds.get(i);
22634e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
22644e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
22654e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (mTargets.size() > 0) {
22664e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                for (int i = 0; i < mTargets.size(); ++i) {
22674e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    if (i > 0) {
22684e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        result += ", ";
22694e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
22704e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    result += mTargets.get(i);
22714e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
22724e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
22734e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            result += ")";
22744e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
22754e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return result;
2276c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
2277c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
2278c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
2279c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * A transition listener receives notifications from a transition.
2280c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Notifications indicate transition lifecycle events.
2281c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
22824e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public interface TransitionListener {
2283c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
2284c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
2285c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * Notification about the start of the transition.
2286c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         *
2287c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * @param transition The started transition.
2288c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
2289cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki        void onTransitionStart(@NonNull Transition transition);
2290c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
2291c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
2292c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * Notification about the end of the transition. Canceled transitions
2293c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * will always notify listeners of both the cancellation and end
2294c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * events. That is, {@link #onTransitionEnd(Transition)} is always called,
2295c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * regardless of whether the transition was canceled or played
2296c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * through to completion.
2297c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         *
2298c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * @param transition The transition which reached its end.
2299c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
2300cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki        void onTransitionEnd(@NonNull Transition transition);
2301c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
2302c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
2303c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * Notification about the cancellation of the transition.
2304c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * Note that cancel may be called by a parent {@link TransitionSet} on
2305c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * a child transition which has not yet started. This allows the child
2306c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * transition to restore state on target objects which was set at
2307c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
2308c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * createAnimator()} time.
2309c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         *
2310c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * @param transition The transition which was canceled.
2311c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
2312cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki        void onTransitionCancel(@NonNull Transition transition);
2313c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
2314c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
2315c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * Notification when a transition is paused.
2316c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * Note that createAnimator() may be called by a parent {@link TransitionSet} on
2317c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * a child transition which has not yet started. This allows the child
2318c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * transition to restore state on target objects which was set at
2319c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)
2320c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * createAnimator()} time.
2321c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         *
2322c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * @param transition The transition which was paused.
2323c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
2324cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki        void onTransitionPause(@NonNull Transition transition);
2325c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
2326c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
2327c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * Notification when a transition is resumed.
2328c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * Note that resume() may be called by a parent {@link TransitionSet} on
2329c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * a child transition which has not yet started. This allows the child
2330c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * transition to restore state which may have changed in an earlier call
2331c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * to {@link #onTransitionPause(Transition)}.
2332c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         *
2333c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * @param transition The transition which was resumed.
2334c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
2335cbba0a52f7d7b593dbb13a138515f066f75cce80Yuichi Araki        void onTransitionResume(@NonNull Transition transition);
2336c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
2337c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
23384e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
23394e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Holds information about each animator used when a new transition starts
23404e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * while other transitions are still running to determine whether a running
23414e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * animation should be canceled or a new animation noop'd. The structure holds
23424e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * information about the state that an animation is going to, to be compared to
23434e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * end state of a new animation.
23444e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
23454e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private static class AnimationInfo {
23464e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
23474e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        View mView;
23484e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
23494e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        String mName;
23504e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
23514e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        TransitionValues mValues;
23524e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
23534e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        WindowIdImpl mWindowId;
23544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
2355756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        Transition mTransition;
2356756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
2357756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        AnimationInfo(View view, String name, Transition transition, WindowIdImpl windowId,
2358756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                TransitionValues values) {
23594e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mView = view;
23604e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mName = name;
23614e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mValues = values;
23624e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            mWindowId = windowId;
2363756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            mTransition = transition;
23644e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
23654e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
23664e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
23674e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    /**
23684e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * Utility class for managing typed ArrayLists efficiently. In particular, this
23694e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * can be useful for lists that we don't expect to be used often (eg, the exclude
23704e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * lists), so we'd like to keep them nulled out by default. This causes the code to
23714e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * become tedious, with constant null checks, code to allocate when necessary,
23724e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * and code to null out the reference when the list is empty. This class encapsulates
23734e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * all of that functionality into simple add()/remove() methods which perform the
23744e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * necessary checks, allocation/null-out as appropriate, and return the
23754e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     * resulting list.
23764e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki     */
23774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private static class ArrayListManager {
23784e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
23794e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        /**
23804e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki         * Add the specified item to the list, returning the resulting list.
23814e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki         * The returned list can either the be same list passed in or, if that
23824e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki         * list was null, the new list that was created.
23834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki         *
23844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki         * Note that the list holds unique items; if the item already exists in the
23854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki         * list, the list is not modified.
23864e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki         */
23874e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        static <T> ArrayList<T> add(ArrayList<T> list, T item) {
23884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (list == null) {
23894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                list = new ArrayList<>();
23904e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
23914e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (!list.contains(item)) {
23924e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                list.add(item);
23934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
23944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return list;
23954e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
23964e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
23974e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        /**
23984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki         * Remove the specified item from the list, returning the resulting list.
23994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki         * The returned list can either the be same list passed in or, if that
24004e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki         * list becomes empty as a result of the remove(), the new list was created.
24014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki         */
24024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        static <T> ArrayList<T> remove(ArrayList<T> list, T item) {
24034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (list != null) {
24044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                list.remove(item);
24054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                if (list.isEmpty()) {
24064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    list = null;
24074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
24084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
24094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return list;
24104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
24114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
24124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
24134c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    /**
24144c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * Class to get the epicenter of Transition. Use
24154c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * {@link #setEpicenterCallback(EpicenterCallback)} to set the callback used to calculate the
24164c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * epicenter of the Transition. Override {@link #getEpicenter()} to return the rectangular
24174c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * region in screen coordinates of the epicenter of the transition.
24184c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     *
24194c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     * @see #setEpicenterCallback(EpicenterCallback)
24204c904b38c763179727b9b5ea7a80454630545663Yuichi Araki     */
24214c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    public abstract static class EpicenterCallback {
24224c904b38c763179727b9b5ea7a80454630545663Yuichi Araki
24234c904b38c763179727b9b5ea7a80454630545663Yuichi Araki        /**
24244c904b38c763179727b9b5ea7a80454630545663Yuichi Araki         * Implementers must override to return the epicenter of the Transition in screen
24254c904b38c763179727b9b5ea7a80454630545663Yuichi Araki         * coordinates. Transitions like {@link android.transition.Explode} depend upon
24264c904b38c763179727b9b5ea7a80454630545663Yuichi Araki         * an epicenter for the Transition. In Explode, Views move toward or away from the
24274c904b38c763179727b9b5ea7a80454630545663Yuichi Araki         * center of the epicenter Rect along the vector between the epicenter and the center
24284c904b38c763179727b9b5ea7a80454630545663Yuichi Araki         * of the View appearing and disappearing. Some Transitions, such as
24294c904b38c763179727b9b5ea7a80454630545663Yuichi Araki         * {@link android.transition.Fade} pay no attention to the epicenter.
24304c904b38c763179727b9b5ea7a80454630545663Yuichi Araki         *
24314c904b38c763179727b9b5ea7a80454630545663Yuichi Araki         * @param transition The transition for which the epicenter applies.
24324c904b38c763179727b9b5ea7a80454630545663Yuichi Araki         * @return The Rect region of the epicenter of <code>transition</code> or null if
24334c904b38c763179727b9b5ea7a80454630545663Yuichi Araki         * there is no epicenter.
24344c904b38c763179727b9b5ea7a80454630545663Yuichi Araki         */
24357f117eb86f61d5f764085a82129600542ba05712Yuichi Araki        public abstract Rect onGetEpicenter(@NonNull Transition transition);
24364c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    }
24374c904b38c763179727b9b5ea7a80454630545663Yuichi Araki
2438c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki}
2439