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 * <changeBounds/> 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 * <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" 988158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * android:transitionOrdering="sequential"> 998158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * <changeBounds/> 1008158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * <fade android:fadingMode="fade_out"> 1018158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * <targets> 1028158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * <target android:targetId="@id/grayscaleContainer"/> 1038158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * </targets> 1048158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * </fade> 1058158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * </transitionSet> 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