131a217290cf376d0573fc36e21c8940987485019George Mount/* 231a217290cf376d0573fc36e21c8940987485019George Mount * Copyright (C) 2014 The Android Open Source Project 331a217290cf376d0573fc36e21c8940987485019George Mount * 431a217290cf376d0573fc36e21c8940987485019George Mount * Licensed under the Apache License, Version 2.0 (the "License"); 531a217290cf376d0573fc36e21c8940987485019George Mount * you may not use this file except in compliance with the License. 631a217290cf376d0573fc36e21c8940987485019George Mount * You may obtain a copy of the License at 731a217290cf376d0573fc36e21c8940987485019George Mount * 831a217290cf376d0573fc36e21c8940987485019George Mount * http://www.apache.org/licenses/LICENSE-2.0 931a217290cf376d0573fc36e21c8940987485019George Mount * 1031a217290cf376d0573fc36e21c8940987485019George Mount * Unless required by applicable law or agreed to in writing, software 1131a217290cf376d0573fc36e21c8940987485019George Mount * distributed under the License is distributed on an "AS IS" BASIS, 1231a217290cf376d0573fc36e21c8940987485019George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1331a217290cf376d0573fc36e21c8940987485019George Mount * See the License for the specific language governing permissions and 1431a217290cf376d0573fc36e21c8940987485019George Mount * limitations under the License. 1531a217290cf376d0573fc36e21c8940987485019George Mount */ 1631a217290cf376d0573fc36e21c8940987485019George Mountpackage android.app; 1731a217290cf376d0573fc36e21c8940987485019George Mount 18c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mountimport android.content.Context; 19c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mountimport android.graphics.Matrix; 2031a217290cf376d0573fc36e21c8940987485019George Mountimport android.graphics.Rect; 217bf379c8af399626d5b8b568fe1d4f96f56badccDake Guimport android.graphics.RectF; 22c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mountimport android.os.Bundle; 2331a217290cf376d0573fc36e21c8940987485019George Mountimport android.os.Handler; 24480ca829e2d3313740b4d14d30afbea6c98ff965George Mountimport android.os.Parcelable; 2531a217290cf376d0573fc36e21c8940987485019George Mountimport android.os.ResultReceiver; 2631a217290cf376d0573fc36e21c8940987485019George Mountimport android.transition.Transition; 27e0c37bdea37f78778f6c4f23f03604e59dfb0d55Ben Weissimport android.transition.TransitionListenerAdapter; 2831a217290cf376d0573fc36e21c8940987485019George Mountimport android.transition.TransitionSet; 291349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mountimport android.transition.Visibility; 3031a217290cf376d0573fc36e21c8940987485019George Mountimport android.util.ArrayMap; 31f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mountimport android.util.ArraySet; 32fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mountimport android.view.GhostView; 3331a217290cf376d0573fc36e21c8940987485019George Mountimport android.view.View; 3431a217290cf376d0573fc36e21c8940987485019George Mountimport android.view.ViewGroup; 35fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mountimport android.view.ViewGroupOverlay; 36fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mountimport android.view.ViewParent; 3741725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mountimport android.view.ViewRootImpl; 38c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mountimport android.view.ViewTreeObserver; 3931a217290cf376d0573fc36e21c8940987485019George Mountimport android.view.Window; 40caa03107d4322b0e30f92e6dc1eb1ea73b1bf747George Mountimport android.widget.ImageView; 4131a217290cf376d0573fc36e21c8940987485019George Mount 42f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mountimport com.android.internal.view.OneShotPreDrawListener; 43f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount 4431a217290cf376d0573fc36e21c8940987485019George Mountimport java.util.ArrayList; 4531a217290cf376d0573fc36e21c8940987485019George Mountimport java.util.Collection; 4631a217290cf376d0573fc36e21c8940987485019George Mount 4731a217290cf376d0573fc36e21c8940987485019George Mount/** 4831a217290cf376d0573fc36e21c8940987485019George Mount * Base class for ExitTransitionCoordinator and EnterTransitionCoordinator, classes 4931a217290cf376d0573fc36e21c8940987485019George Mount * that manage activity transitions and the communications coordinating them between 5031a217290cf376d0573fc36e21c8940987485019George Mount * Activities. The ExitTransitionCoordinator is created in the 5131a217290cf376d0573fc36e21c8940987485019George Mount * ActivityOptions#makeSceneTransitionAnimation. The EnterTransitionCoordinator 5231a217290cf376d0573fc36e21c8940987485019George Mount * is created by ActivityOptions#createEnterActivityTransition by Activity when the window is 5331a217290cf376d0573fc36e21c8940987485019George Mount * attached. 5431a217290cf376d0573fc36e21c8940987485019George Mount * 5531a217290cf376d0573fc36e21c8940987485019George Mount * Typical startActivity goes like this: 5631a217290cf376d0573fc36e21c8940987485019George Mount * 1) ExitTransitionCoordinator created with ActivityOptions#makeSceneTransitionAnimation 5731a217290cf376d0573fc36e21c8940987485019George Mount * 2) Activity#startActivity called and that calls startExit() through 5831a217290cf376d0573fc36e21c8940987485019George Mount * ActivityOptions#dispatchStartExit 5931a217290cf376d0573fc36e21c8940987485019George Mount * - Exit transition starts by setting transitioning Views to INVISIBLE 6031a217290cf376d0573fc36e21c8940987485019George Mount * 3) Launched Activity starts, creating an EnterTransitionCoordinator. 6131a217290cf376d0573fc36e21c8940987485019George Mount * - The Window is made translucent 6231a217290cf376d0573fc36e21c8940987485019George Mount * - The Window background alpha is set to 0 6331a217290cf376d0573fc36e21c8940987485019George Mount * - The transitioning views are made INVISIBLE 6431a217290cf376d0573fc36e21c8940987485019George Mount * - MSG_SET_LISTENER is sent back to the ExitTransitionCoordinator. 6531a217290cf376d0573fc36e21c8940987485019George Mount * 4) The shared element transition completes. 6631a217290cf376d0573fc36e21c8940987485019George Mount * - MSG_TAKE_SHARED_ELEMENTS is sent to the EnterTransitionCoordinator 6731a217290cf376d0573fc36e21c8940987485019George Mount * 5) The MSG_TAKE_SHARED_ELEMENTS is received by the EnterTransitionCoordinator. 6831a217290cf376d0573fc36e21c8940987485019George Mount * - Shared elements are made VISIBLE 6931a217290cf376d0573fc36e21c8940987485019George Mount * - Shared elements positions and size are set to match the end state of the calling 7031a217290cf376d0573fc36e21c8940987485019George Mount * Activity. 7131a217290cf376d0573fc36e21c8940987485019George Mount * - The shared element transition is started 7231a217290cf376d0573fc36e21c8940987485019George Mount * - If the window allows overlapping transitions, the views transition is started by setting 7331a217290cf376d0573fc36e21c8940987485019George Mount * the entering Views to VISIBLE and the background alpha is animated to opaque. 7431a217290cf376d0573fc36e21c8940987485019George Mount * - MSG_HIDE_SHARED_ELEMENTS is sent to the ExitTransitionCoordinator 7531a217290cf376d0573fc36e21c8940987485019George Mount * 6) MSG_HIDE_SHARED_ELEMENTS is received by the ExitTransitionCoordinator 7631a217290cf376d0573fc36e21c8940987485019George Mount * - The shared elements are made INVISIBLE 7731a217290cf376d0573fc36e21c8940987485019George Mount * 7) The exit transition completes in the calling Activity. 7831a217290cf376d0573fc36e21c8940987485019George Mount * - MSG_EXIT_TRANSITION_COMPLETE is sent to the EnterTransitionCoordinator. 7931a217290cf376d0573fc36e21c8940987485019George Mount * 8) The MSG_EXIT_TRANSITION_COMPLETE is received by the EnterTransitionCoordinator. 8031a217290cf376d0573fc36e21c8940987485019George Mount * - If the window doesn't allow overlapping enter transitions, the enter transition is started 8131a217290cf376d0573fc36e21c8940987485019George Mount * by setting entering views to VISIBLE and the background is animated to opaque. 8231a217290cf376d0573fc36e21c8940987485019George Mount * 9) The background opacity animation completes. 8331a217290cf376d0573fc36e21c8940987485019George Mount * - The window is made opaque 8431a217290cf376d0573fc36e21c8940987485019George Mount * 10) The calling Activity gets an onStop() call 8531a217290cf376d0573fc36e21c8940987485019George Mount * - onActivityStopped() is called and all exited Views are made VISIBLE. 8631a217290cf376d0573fc36e21c8940987485019George Mount * 8773f843de4b65772c624ca8ebb8c976a279e37ce9Craig Mautner * Typical finishAfterTransition goes like this: 8873f843de4b65772c624ca8ebb8c976a279e37ce9Craig Mautner * 1) finishAfterTransition() creates an ExitTransitionCoordinator and calls startExit() 8962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * - The Window start transitioning to Translucent with a new ActivityOptions. 9031a217290cf376d0573fc36e21c8940987485019George Mount * - If no background exists, a black background is substituted 9131a217290cf376d0573fc36e21c8940987485019George Mount * - The shared elements in the scene are matched against those shared elements 9231a217290cf376d0573fc36e21c8940987485019George Mount * that were sent by comparing the names. 9331a217290cf376d0573fc36e21c8940987485019George Mount * - The exit transition is started by setting Views to INVISIBLE. 9462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * 2) The ActivityOptions is received by the Activity and an EnterTransitionCoordinator is created. 9531a217290cf376d0573fc36e21c8940987485019George Mount * - All transitioning views are made VISIBLE to reverse what was done when onActivityStopped() 9631a217290cf376d0573fc36e21c8940987485019George Mount * was called 9731a217290cf376d0573fc36e21c8940987485019George Mount * 3) The Window is made translucent and a callback is received 9831a217290cf376d0573fc36e21c8940987485019George Mount * - The background alpha is animated to 0 9931a217290cf376d0573fc36e21c8940987485019George Mount * 4) The background alpha animation completes 10031a217290cf376d0573fc36e21c8940987485019George Mount * 5) The shared element transition completes 10131a217290cf376d0573fc36e21c8940987485019George Mount * - After both 4 & 5 complete, MSG_TAKE_SHARED_ELEMENTS is sent to the 10262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * EnterTransitionCoordinator 10362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * 6) MSG_TAKE_SHARED_ELEMENTS is received by EnterTransitionCoordinator 10431a217290cf376d0573fc36e21c8940987485019George Mount * - Shared elements are made VISIBLE 10531a217290cf376d0573fc36e21c8940987485019George Mount * - Shared elements positions and size are set to match the end state of the calling 10631a217290cf376d0573fc36e21c8940987485019George Mount * Activity. 10731a217290cf376d0573fc36e21c8940987485019George Mount * - The shared element transition is started 10831a217290cf376d0573fc36e21c8940987485019George Mount * - If the window allows overlapping transitions, the views transition is started by setting 10931a217290cf376d0573fc36e21c8940987485019George Mount * the entering Views to VISIBLE. 11062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * - MSG_HIDE_SHARED_ELEMENTS is sent to the ExitTransitionCoordinator 11162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * 7) MSG_HIDE_SHARED_ELEMENTS is received by the ExitTransitionCoordinator 11231a217290cf376d0573fc36e21c8940987485019George Mount * - The shared elements are made INVISIBLE 11331a217290cf376d0573fc36e21c8940987485019George Mount * 8) The exit transition completes in the finishing Activity. 11462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * - MSG_EXIT_TRANSITION_COMPLETE is sent to the EnterTransitionCoordinator. 11531a217290cf376d0573fc36e21c8940987485019George Mount * - finish() is called on the exiting Activity 11662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * 9) The MSG_EXIT_TRANSITION_COMPLETE is received by the EnterTransitionCoordinator. 11731a217290cf376d0573fc36e21c8940987485019George Mount * - If the window doesn't allow overlapping enter transitions, the enter transition is started 11831a217290cf376d0573fc36e21c8940987485019George Mount * by setting entering views to VISIBLE. 11931a217290cf376d0573fc36e21c8940987485019George Mount */ 12031a217290cf376d0573fc36e21c8940987485019George Mountabstract class ActivityTransitionCoordinator extends ResultReceiver { 12131a217290cf376d0573fc36e21c8940987485019George Mount private static final String TAG = "ActivityTransitionCoordinator"; 12231a217290cf376d0573fc36e21c8940987485019George Mount 12331a217290cf376d0573fc36e21c8940987485019George Mount /** 12431a217290cf376d0573fc36e21c8940987485019George Mount * For Activity transitions, the called Activity's listener to receive calls 12531a217290cf376d0573fc36e21c8940987485019George Mount * when transitions complete. 12631a217290cf376d0573fc36e21c8940987485019George Mount */ 12762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount static final String KEY_REMOTE_RECEIVER = "android:remoteReceiver"; 12862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount 1297bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu protected static final String KEY_SCREEN_LEFT = "shared_element:screenLeft"; 1307bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu protected static final String KEY_SCREEN_TOP = "shared_element:screenTop"; 1317bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu protected static final String KEY_SCREEN_RIGHT = "shared_element:screenRight"; 1327bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu protected static final String KEY_SCREEN_BOTTOM= "shared_element:screenBottom"; 13362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount protected static final String KEY_TRANSLATION_Z = "shared_element:translationZ"; 134480ca829e2d3313740b4d14d30afbea6c98ff965George Mount protected static final String KEY_SNAPSHOT = "shared_element:bitmap"; 13562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount protected static final String KEY_SCALE_TYPE = "shared_element:scaleType"; 13662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount protected static final String KEY_IMAGE_MATRIX = "shared_element:imageMatrix"; 13726c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount protected static final String KEY_ELEVATION = "shared_element:elevation"; 13831a217290cf376d0573fc36e21c8940987485019George Mount 13962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount protected static final ImageView.ScaleType[] SCALE_TYPE_VALUES = ImageView.ScaleType.values(); 14031a217290cf376d0573fc36e21c8940987485019George Mount 14131a217290cf376d0573fc36e21c8940987485019George Mount /** 14231a217290cf376d0573fc36e21c8940987485019George Mount * Sent by the exiting coordinator (either EnterTransitionCoordinator 14331a217290cf376d0573fc36e21c8940987485019George Mount * or ExitTransitionCoordinator) after the shared elements have 14431a217290cf376d0573fc36e21c8940987485019George Mount * become stationary (shared element transition completes). This tells 14531a217290cf376d0573fc36e21c8940987485019George Mount * the remote coordinator to take control of the shared elements and 14631a217290cf376d0573fc36e21c8940987485019George Mount * that animations may begin. The remote Activity won't start entering 14731a217290cf376d0573fc36e21c8940987485019George Mount * until this message is received, but may wait for 14831a217290cf376d0573fc36e21c8940987485019George Mount * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true. 14931a217290cf376d0573fc36e21c8940987485019George Mount */ 15062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount public static final int MSG_SET_REMOTE_RECEIVER = 100; 15131a217290cf376d0573fc36e21c8940987485019George Mount 15231a217290cf376d0573fc36e21c8940987485019George Mount /** 15331a217290cf376d0573fc36e21c8940987485019George Mount * Sent by the entering coordinator to tell the exiting coordinator 15431a217290cf376d0573fc36e21c8940987485019George Mount * to hide its shared elements after it has started its shared 15531a217290cf376d0573fc36e21c8940987485019George Mount * element transition. This is temporary until the 15631a217290cf376d0573fc36e21c8940987485019George Mount * interlock of shared elements is figured out. 15731a217290cf376d0573fc36e21c8940987485019George Mount */ 15831a217290cf376d0573fc36e21c8940987485019George Mount public static final int MSG_HIDE_SHARED_ELEMENTS = 101; 15931a217290cf376d0573fc36e21c8940987485019George Mount 16031a217290cf376d0573fc36e21c8940987485019George Mount /** 16131a217290cf376d0573fc36e21c8940987485019George Mount * Sent by the exiting coordinator (either EnterTransitionCoordinator 16231a217290cf376d0573fc36e21c8940987485019George Mount * or ExitTransitionCoordinator) after the shared elements have 16331a217290cf376d0573fc36e21c8940987485019George Mount * become stationary (shared element transition completes). This tells 16431a217290cf376d0573fc36e21c8940987485019George Mount * the remote coordinator to take control of the shared elements and 16531a217290cf376d0573fc36e21c8940987485019George Mount * that animations may begin. The remote Activity won't start entering 16631a217290cf376d0573fc36e21c8940987485019George Mount * until this message is received, but may wait for 16731a217290cf376d0573fc36e21c8940987485019George Mount * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true. 16831a217290cf376d0573fc36e21c8940987485019George Mount */ 16962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount public static final int MSG_TAKE_SHARED_ELEMENTS = 103; 17031a217290cf376d0573fc36e21c8940987485019George Mount 17131a217290cf376d0573fc36e21c8940987485019George Mount /** 17231a217290cf376d0573fc36e21c8940987485019George Mount * Sent by the exiting coordinator (either 17331a217290cf376d0573fc36e21c8940987485019George Mount * EnterTransitionCoordinator or ExitTransitionCoordinator) after 17431a217290cf376d0573fc36e21c8940987485019George Mount * the exiting Views have finished leaving the scene. This will 17531a217290cf376d0573fc36e21c8940987485019George Mount * be ignored if allowOverlappingTransitions() is true on the 17631a217290cf376d0573fc36e21c8940987485019George Mount * remote coordinator. If it is false, it will trigger the enter 17731a217290cf376d0573fc36e21c8940987485019George Mount * transition to start. 17831a217290cf376d0573fc36e21c8940987485019George Mount */ 17962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount public static final int MSG_EXIT_TRANSITION_COMPLETE = 104; 18031a217290cf376d0573fc36e21c8940987485019George Mount 18131a217290cf376d0573fc36e21c8940987485019George Mount /** 18231a217290cf376d0573fc36e21c8940987485019George Mount * Sent by Activity#startActivity to begin the exit transition. 18331a217290cf376d0573fc36e21c8940987485019George Mount */ 18462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount public static final int MSG_START_EXIT_TRANSITION = 105; 18531a217290cf376d0573fc36e21c8940987485019George Mount 18631a217290cf376d0573fc36e21c8940987485019George Mount /** 18762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * It took too long for a message from the entering Activity, so we canceled the transition. 18831a217290cf376d0573fc36e21c8940987485019George Mount */ 18962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount public static final int MSG_CANCEL = 106; 19062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount 191c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount /** 192c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount * When returning, this is the destination location for the shared element. 193c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount */ 194c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount public static final int MSG_SHARED_ELEMENT_DESTINATION = 107; 195c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 196a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount private Window mWindow; 19762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount final protected ArrayList<String> mAllSharedElementNames; 19862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount final protected ArrayList<View> mSharedElements = new ArrayList<View>(); 19962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount final protected ArrayList<String> mSharedElementNames = new ArrayList<String>(); 200b694e080546316a27d22eba759027f6cb0a24705George Mount protected ArrayList<View> mTransitioningViews = new ArrayList<View>(); 2016558056e8fccc32f9e1dc59e46d09f8d916b7538George Mount protected SharedElementCallback mListener; 20262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount protected ResultReceiver mResultReceiver; 20362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount final private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback(); 204c9b6df8fa4df3968b2420a52c5281b4765478f68George Mount final protected boolean mIsReturning; 20567d924341a1d0994ac68b3b7898d5576edd987b4George Mount private Runnable mPendingTransition; 20667d924341a1d0994ac68b3b7898d5576edd987b4George Mount private boolean mIsStartingTransition; 207fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount private ArrayList<GhostViewListeners> mGhostViewListeners = 208fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount new ArrayList<GhostViewListeners>(); 2090f0c473488f8e8becc8883d3cdd9610324610dc4George Mount private ArrayMap<View, Float> mOriginalAlphas = new ArrayMap<View, Float>(); 210333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount private ArrayList<Matrix> mSharedElementParentMatrices; 21141725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount private boolean mSharedElementTransitionComplete; 21241725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount private boolean mViewsTransitionComplete; 213b64e777f6c14d862f221f4da814079df22663db1Chet Haase private boolean mBackgroundAnimatorComplete; 214aae763e692810fb411b83fdda57567e1b66577ddGeorge Mount private ArrayList<View> mStrippedTransitioningViews = new ArrayList<>(); 21567d924341a1d0994ac68b3b7898d5576edd987b4George Mount 2168c2614ce4328640642d8e8be437859e0508a39b4George Mount public ActivityTransitionCoordinator(Window window, 2178c2614ce4328640642d8e8be437859e0508a39b4George Mount ArrayList<String> allSharedElementNames, 2186558056e8fccc32f9e1dc59e46d09f8d916b7538George Mount SharedElementCallback listener, boolean isReturning) { 21962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount super(new Handler()); 22062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount mWindow = window; 22162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount mListener = listener; 22262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount mAllSharedElementNames = allSharedElementNames; 223c9b6df8fa4df3968b2420a52c5281b4765478f68George Mount mIsReturning = isReturning; 2248c2614ce4328640642d8e8be437859e0508a39b4George Mount } 2258c2614ce4328640642d8e8be437859e0508a39b4George Mount 2261fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount protected void viewsReady(ArrayMap<String, View> sharedElements) { 227ce725a47f6eee75a6ef86397e9b9fe471aeb1f84George Mount sharedElements.retainAll(mAllSharedElementNames); 2281732f528952ea2df0bfd503fabb958af03dbfc81George Mount if (mListener != null) { 2291732f528952ea2df0bfd503fabb958af03dbfc81George Mount mListener.onMapSharedElements(mAllSharedElementNames, sharedElements); 2301732f528952ea2df0bfd503fabb958af03dbfc81George Mount } 231333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount setSharedElements(sharedElements); 232b694e080546316a27d22eba759027f6cb0a24705George Mount if (getViewsTransition() != null && mTransitioningViews != null) { 23348bd13c9cb2627847cf1f7707a084eb354e9c303George Mount ViewGroup decorView = getDecor(); 23448bd13c9cb2627847cf1f7707a084eb354e9c303George Mount if (decorView != null) { 23548bd13c9cb2627847cf1f7707a084eb354e9c303George Mount decorView.captureTransitioningViews(mTransitioningViews); 23648bd13c9cb2627847cf1f7707a084eb354e9c303George Mount } 23762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount mTransitioningViews.removeAll(mSharedElements); 23831a217290cf376d0573fc36e21c8940987485019George Mount } 23962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount setEpicenter(); 24031a217290cf376d0573fc36e21c8940987485019George Mount } 24131a217290cf376d0573fc36e21c8940987485019George Mount 242333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount /** 243333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount * Iterates over the shared elements and adds them to the members in order. 244333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount * Shared elements that are nested in other shared elements are placed after the 245333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount * elements that they are nested in. This means that layout ordering can be done 246333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount * from first to last. 247333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount * 248333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount * @param sharedElements The map of transition names to shared elements to set into 249333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount * the member fields. 250333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount */ 251333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount private void setSharedElements(ArrayMap<String, View> sharedElements) { 252333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount boolean isFirstRun = true; 253333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount while (!sharedElements.isEmpty()) { 254333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount final int numSharedElements = sharedElements.size(); 255333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount for (int i = numSharedElements - 1; i >= 0; i--) { 256333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount final View view = sharedElements.valueAt(i); 257333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount final String name = sharedElements.keyAt(i); 258333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount if (isFirstRun && (view == null || !view.isAttachedToWindow() || name == null)) { 259333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount sharedElements.removeAt(i); 26042161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount } else if (!isNested(view, sharedElements)) { 26142161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount mSharedElementNames.add(name); 26242161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount mSharedElements.add(view); 26342161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount sharedElements.removeAt(i); 264333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 265333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 266333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount isFirstRun = false; 267333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 268333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 269333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount 270333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount /** 271333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount * Returns true when view is nested in any of the values of sharedElements. 272333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount */ 273333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount private static boolean isNested(View view, ArrayMap<String, View> sharedElements) { 274333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount ViewParent parent = view.getParent(); 275333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount boolean isNested = false; 276333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount while (parent instanceof View) { 277333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount View parentView = (View) parent; 278333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount if (sharedElements.containsValue(parentView)) { 279333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount isNested = true; 280333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount break; 281333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 282333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount parent = parentView.getParent(); 283333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 284333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount return isNested; 285333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 286333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount 28760625b02ac099bacc96a387ec270751745dafae0George Mount protected void stripOffscreenViews() { 288b694e080546316a27d22eba759027f6cb0a24705George Mount if (mTransitioningViews == null) { 289b694e080546316a27d22eba759027f6cb0a24705George Mount return; 290b694e080546316a27d22eba759027f6cb0a24705George Mount } 29160625b02ac099bacc96a387ec270751745dafae0George Mount Rect r = new Rect(); 29260625b02ac099bacc96a387ec270751745dafae0George Mount for (int i = mTransitioningViews.size() - 1; i >= 0; i--) { 29360625b02ac099bacc96a387ec270751745dafae0George Mount View view = mTransitioningViews.get(i); 29460625b02ac099bacc96a387ec270751745dafae0George Mount if (!view.getGlobalVisibleRect(r)) { 29560625b02ac099bacc96a387ec270751745dafae0George Mount mTransitioningViews.remove(i); 296aae763e692810fb411b83fdda57567e1b66577ddGeorge Mount mStrippedTransitioningViews.add(view); 29760625b02ac099bacc96a387ec270751745dafae0George Mount } 29860625b02ac099bacc96a387ec270751745dafae0George Mount } 29960625b02ac099bacc96a387ec270751745dafae0George Mount } 30060625b02ac099bacc96a387ec270751745dafae0George Mount 30131a217290cf376d0573fc36e21c8940987485019George Mount protected Window getWindow() { 30231a217290cf376d0573fc36e21c8940987485019George Mount return mWindow; 30331a217290cf376d0573fc36e21c8940987485019George Mount } 30431a217290cf376d0573fc36e21c8940987485019George Mount 305a2bbbb3bac464c3a52e33008401fed4a7542744cGeorge Mount public ViewGroup getDecor() { 30631a217290cf376d0573fc36e21c8940987485019George Mount return (mWindow == null) ? null : (ViewGroup) mWindow.getDecorView(); 30731a217290cf376d0573fc36e21c8940987485019George Mount } 30831a217290cf376d0573fc36e21c8940987485019George Mount 30962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount /** 31062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * Sets the transition epicenter to the position of the first shared element. 31162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount */ 31262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount protected void setEpicenter() { 31362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount View epicenter = null; 314c6186bffe477b996e388046e8761908b813fd07fGeorge Mount if (!mAllSharedElementNames.isEmpty() && !mSharedElementNames.isEmpty()) { 315c6186bffe477b996e388046e8761908b813fd07fGeorge Mount int index = mSharedElementNames.indexOf(mAllSharedElementNames.get(0)); 316c6186bffe477b996e388046e8761908b813fd07fGeorge Mount if (index >= 0) { 317c6186bffe477b996e388046e8761908b813fd07fGeorge Mount epicenter = mSharedElements.get(index); 318c6186bffe477b996e388046e8761908b813fd07fGeorge Mount } 31931a217290cf376d0573fc36e21c8940987485019George Mount } 32062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount setEpicenter(epicenter); 32131a217290cf376d0573fc36e21c8940987485019George Mount } 32231a217290cf376d0573fc36e21c8940987485019George Mount 32362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount private void setEpicenter(View view) { 32462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount if (view == null) { 32562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount mEpicenterCallback.setEpicenter(null); 32631a217290cf376d0573fc36e21c8940987485019George Mount } else { 3278e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount Rect epicenter = new Rect(); 3288e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount view.getBoundsOnScreen(epicenter); 32962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount mEpicenterCallback.setEpicenter(epicenter); 33031a217290cf376d0573fc36e21c8940987485019George Mount } 33131a217290cf376d0573fc36e21c8940987485019George Mount } 33231a217290cf376d0573fc36e21c8940987485019George Mount 33362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount public ArrayList<String> getAcceptedNames() { 33462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount return mSharedElementNames; 33531a217290cf376d0573fc36e21c8940987485019George Mount } 33631a217290cf376d0573fc36e21c8940987485019George Mount 33762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount public ArrayList<String> getMappedNames() { 33862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount ArrayList<String> names = new ArrayList<String>(mSharedElements.size()); 33962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount for (int i = 0; i < mSharedElements.size(); i++) { 3400a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount names.add(mSharedElements.get(i).getTransitionName()); 341080443bcb63418245c2408500db735fece5e7083George Mount } 34262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount return names; 34331a217290cf376d0573fc36e21c8940987485019George Mount } 34431a217290cf376d0573fc36e21c8940987485019George Mount 345700db2a325bced35cebc403f272f988fad522892George Mount public ArrayList<View> copyMappedViews() { 346700db2a325bced35cebc403f272f988fad522892George Mount return new ArrayList<View>(mSharedElements); 3471fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount } 3481fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount 3498c2614ce4328640642d8e8be437859e0508a39b4George Mount public ArrayList<String> getAllSharedElementNames() { return mAllSharedElementNames; } 3508c2614ce4328640642d8e8be437859e0508a39b4George Mount 3518881502da5b319e139ab85c1825d2d2d239356a1George Mount protected Transition setTargets(Transition transition, boolean add) { 3528881502da5b319e139ab85c1825d2d2d239356a1George Mount if (transition == null || (add && 3538881502da5b319e139ab85c1825d2d2d239356a1George Mount (mTransitioningViews == null || mTransitioningViews.isEmpty()))) { 35431a217290cf376d0573fc36e21c8940987485019George Mount return null; 35531a217290cf376d0573fc36e21c8940987485019George Mount } 356d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount // Add the targets to a set containing transition so that transition 357d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount // remains unaffected. We don't want to modify the targets of transition itself. 35831a217290cf376d0573fc36e21c8940987485019George Mount TransitionSet set = new TransitionSet(); 3598881502da5b319e139ab85c1825d2d2d239356a1George Mount if (mTransitioningViews != null) { 3608881502da5b319e139ab85c1825d2d2d239356a1George Mount for (int i = mTransitioningViews.size() - 1; i >= 0; i--) { 3618881502da5b319e139ab85c1825d2d2d239356a1George Mount View view = mTransitioningViews.get(i); 3628881502da5b319e139ab85c1825d2d2d239356a1George Mount if (add) { 3638881502da5b319e139ab85c1825d2d2d239356a1George Mount set.addTarget(view); 3648881502da5b319e139ab85c1825d2d2d239356a1George Mount } else { 3658881502da5b319e139ab85c1825d2d2d239356a1George Mount set.excludeTarget(view, true); 3668881502da5b319e139ab85c1825d2d2d239356a1George Mount } 36731a217290cf376d0573fc36e21c8940987485019George Mount } 36831a217290cf376d0573fc36e21c8940987485019George Mount } 369aae763e692810fb411b83fdda57567e1b66577ddGeorge Mount if (mStrippedTransitioningViews != null) { 370aae763e692810fb411b83fdda57567e1b66577ddGeorge Mount for (int i = mStrippedTransitioningViews.size() - 1; i >= 0; i--) { 371aae763e692810fb411b83fdda57567e1b66577ddGeorge Mount View view = mStrippedTransitioningViews.get(i); 372aae763e692810fb411b83fdda57567e1b66577ddGeorge Mount set.excludeTarget(view, true); 373aae763e692810fb411b83fdda57567e1b66577ddGeorge Mount } 374aae763e692810fb411b83fdda57567e1b66577ddGeorge Mount } 375d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount // By adding the transition after addTarget, we prevent addTarget from 376d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount // affecting transition. 377d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount set.addTransition(transition); 378fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 379fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount if (!add && mTransitioningViews != null && !mTransitioningViews.isEmpty()) { 380fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount // Allow children of excluded transitioning views, but not the views themselves 381fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount set = new TransitionSet().addTransition(set); 382fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 383fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 38431a217290cf376d0573fc36e21c8940987485019George Mount return set; 38531a217290cf376d0573fc36e21c8940987485019George Mount } 38631a217290cf376d0573fc36e21c8940987485019George Mount 3878881502da5b319e139ab85c1825d2d2d239356a1George Mount protected Transition configureTransition(Transition transition, 3888881502da5b319e139ab85c1825d2d2d239356a1George Mount boolean includeTransitioningViews) { 38931a217290cf376d0573fc36e21c8940987485019George Mount if (transition != null) { 39062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount transition = transition.clone(); 39162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount transition.setEpicenterCallback(mEpicenterCallback); 3928881502da5b319e139ab85c1825d2d2d239356a1George Mount transition = setTargets(transition, includeTransitioningViews); 39331a217290cf376d0573fc36e21c8940987485019George Mount } 3941349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount noLayoutSuppressionForVisibilityTransitions(transition); 39531a217290cf376d0573fc36e21c8940987485019George Mount return transition; 39631a217290cf376d0573fc36e21c8940987485019George Mount } 39731a217290cf376d0573fc36e21c8940987485019George Mount 398f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount /** 399f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * Looks through the transition to see which Views have been included and which have been 400f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * excluded. {@code views} will be modified to contain only those Views that are included 401f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * in the transition. If {@code transition} is a TransitionSet, it will search through all 402f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * contained Transitions to find targeted Views. 403f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * 404f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * @param transition The transition to look through for inclusion of Views 405f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * @param views The list of Views that are to be checked for inclusion. Will be modified 406f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * to remove all excluded Views, possibly leaving an empty list. 407f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount */ 408f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount protected static void removeExcludedViews(Transition transition, ArrayList<View> views) { 409f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount ArraySet<View> included = new ArraySet<>(); 410f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount findIncludedViews(transition, views, included); 411f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount views.clear(); 412f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount views.addAll(included); 413f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount } 414f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount 415f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount /** 416f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * Looks through the transition to see which Views have been included. Only {@code views} 417f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * will be examined for inclusion. If {@code transition} is a TransitionSet, it will search 418f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * through all contained Transitions to find targeted Views. 419f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * 420f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * @param transition The transition to look through for inclusion of Views 421f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * @param views The list of Views that are to be checked for inclusion. 422f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * @param included Modified to contain all Views in views that have at least one Transition 423f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount * that affects it. 424f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount */ 425f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount private static void findIncludedViews(Transition transition, ArrayList<View> views, 426f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount ArraySet<View> included) { 427f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount if (transition instanceof TransitionSet) { 428f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount TransitionSet set = (TransitionSet) transition; 429f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount ArrayList<View> includedViews = new ArrayList<>(); 430f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount final int numViews = views.size(); 431f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount for (int i = 0; i < numViews; i++) { 432f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount final View view = views.get(i); 433f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount if (transition.isValidTarget(view)) { 434f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount includedViews.add(view); 435f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount } 436f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount } 437f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount final int count = set.getTransitionCount(); 438f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount for (int i = 0; i < count; i++) { 439f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount findIncludedViews(set.getTransitionAt(i), includedViews, included); 440f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount } 441f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount } else { 442f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount final int numViews = views.size(); 443f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount for (int i = 0; i < numViews; i++) { 444f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount final View view = views.get(i); 445f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount if (transition.isValidTarget(view)) { 446f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount included.add(view); 447f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount } 448f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount } 449f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount } 450f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount } 451f85b3d48d692e60af0b01ce75424ccb68e11b2bbGeorge Mount 45262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount protected static Transition mergeTransitions(Transition transition1, Transition transition2) { 45362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount if (transition1 == null) { 45462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount return transition2; 45562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount } else if (transition2 == null) { 45662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount return transition1; 45762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount } else { 45862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount TransitionSet transitionSet = new TransitionSet(); 45962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount transitionSet.addTransition(transition1); 46062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount transitionSet.addTransition(transition2); 46162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount return transitionSet; 46262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount } 46362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount } 46462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount 4651fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount protected ArrayMap<String, View> mapSharedElements(ArrayList<String> accepted, 4661fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount ArrayList<View> localViews) { 4671fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount ArrayMap<String, View> sharedElements = new ArrayMap<String, View>(); 468ce725a47f6eee75a6ef86397e9b9fe471aeb1f84George Mount if (accepted != null) { 469ce725a47f6eee75a6ef86397e9b9fe471aeb1f84George Mount for (int i = 0; i < accepted.size(); i++) { 470ce725a47f6eee75a6ef86397e9b9fe471aeb1f84George Mount sharedElements.put(accepted.get(i), localViews.get(i)); 471caa03107d4322b0e30f92e6dc1eb1ea73b1bf747George Mount } 472ce725a47f6eee75a6ef86397e9b9fe471aeb1f84George Mount } else { 47348bd13c9cb2627847cf1f7707a084eb354e9c303George Mount ViewGroup decorView = getDecor(); 47448bd13c9cb2627847cf1f7707a084eb354e9c303George Mount if (decorView != null) { 47548bd13c9cb2627847cf1f7707a084eb354e9c303George Mount decorView.findNamedViews(sharedElements); 47648bd13c9cb2627847cf1f7707a084eb354e9c303George Mount } 4771fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount } 4781fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount return sharedElements; 4791fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount } 4801fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount 48162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount protected void setResultReceiver(ResultReceiver resultReceiver) { 48262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount mResultReceiver = resultReceiver; 483080443bcb63418245c2408500db735fece5e7083George Mount } 484080443bcb63418245c2408500db735fece5e7083George Mount 485a712e8cc2f16ac32ee5f1bbf5b962969f2f3451eGeorge Mount protected abstract Transition getViewsTransition(); 486080443bcb63418245c2408500db735fece5e7083George Mount 487fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount private void setSharedElementState(View view, String name, Bundle transitionArgs, 4887bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu Matrix tempMatrix, RectF tempRect, int[] decorLoc) { 489c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount Bundle sharedElementBundle = transitionArgs.getBundle(name); 490c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (sharedElementBundle == null) { 491c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount return; 492c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 493c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 494c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (view instanceof ImageView) { 495c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount int scaleTypeInt = sharedElementBundle.getInt(KEY_SCALE_TYPE, -1); 496c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (scaleTypeInt >= 0) { 497c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount ImageView imageView = (ImageView) view; 498c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount ImageView.ScaleType scaleType = SCALE_TYPE_VALUES[scaleTypeInt]; 499c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount imageView.setScaleType(scaleType); 500c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (scaleType == ImageView.ScaleType.MATRIX) { 501c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount float[] matrixValues = sharedElementBundle.getFloatArray(KEY_IMAGE_MATRIX); 5027bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu tempMatrix.setValues(matrixValues); 5037bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu imageView.setImageMatrix(tempMatrix); 504c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 505c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 506c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 507c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 508c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z); 509c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount view.setTranslationZ(z); 51026c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount float elevation = sharedElementBundle.getFloat(KEY_ELEVATION); 51126c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount view.setElevation(elevation); 512c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 5137bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu float left = sharedElementBundle.getFloat(KEY_SCREEN_LEFT); 5147bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu float top = sharedElementBundle.getFloat(KEY_SCREEN_TOP); 5157bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu float right = sharedElementBundle.getFloat(KEY_SCREEN_RIGHT); 5167bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu float bottom = sharedElementBundle.getFloat(KEY_SCREEN_BOTTOM); 517c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 5187bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu if (decorLoc != null) { 5197bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu left -= decorLoc[0]; 5207bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu top -= decorLoc[1]; 521480ca829e2d3313740b4d14d30afbea6c98ff965George Mount right -= decorLoc[0]; 522480ca829e2d3313740b4d14d30afbea6c98ff965George Mount bottom -= decorLoc[1]; 5237bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu } else { 5247bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu // Find the location in the view's parent 525fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount getSharedElementParentMatrix(view, tempMatrix); 5267bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu tempRect.set(left, top, right, bottom); 5277bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu tempMatrix.mapRect(tempRect); 5287bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu 5297bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu float leftInParent = tempRect.left; 5307bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu float topInParent = tempRect.top; 5317bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu 5327bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu // Find the size of the view 5337bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu view.getInverseMatrix().mapRect(tempRect); 5347bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu float width = tempRect.width(); 5357bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu float height = tempRect.height(); 5367bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu 5377bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu // Now determine the offset due to view transform: 5387bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu view.setLeft(0); 5397bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu view.setTop(0); 5407bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu view.setRight(Math.round(width)); 5417bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu view.setBottom(Math.round(height)); 5427bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu tempRect.set(0, 0, width, height); 5437bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu view.getMatrix().mapRect(tempRect); 5447bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu 54518c2b0ef36400f4af6ee38dd84e2d65d18474b20Doris Liu left = leftInParent - tempRect.left; 54618c2b0ef36400f4af6ee38dd84e2d65d18474b20Doris Liu top = topInParent - tempRect.top; 5477bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu right = left + width; 5487bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu bottom = top + height; 5497bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu } 5507bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu 5517bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu int x = Math.round(left); 5527bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu int y = Math.round(top); 5537bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu int width = Math.round(right) - x; 5547bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu int height = Math.round(bottom) - y; 555c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY); 556c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY); 557c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount view.measure(widthSpec, heightSpec); 558c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 5597bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu view.layout(x, y, x + width, y + height); 560c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 561c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 562333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount private void setSharedElementMatrices() { 563333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount int numSharedElements = mSharedElements.size(); 564333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount if (numSharedElements > 0) { 565333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount mSharedElementParentMatrices = new ArrayList<Matrix>(numSharedElements); 566333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 567333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount for (int i = 0; i < numSharedElements; i++) { 568333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount View view = mSharedElements.get(i); 569333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount 570333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount // Find the location in the view's parent 571333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount ViewGroup parent = (ViewGroup) view.getParent(); 572333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount Matrix matrix = new Matrix(); 573e06b816e0ec64bac284d44c543166e88c9167889George Mount if (parent != null) { 574e06b816e0ec64bac284d44c543166e88c9167889George Mount parent.transformMatrixToLocal(matrix); 575e06b816e0ec64bac284d44c543166e88c9167889George Mount matrix.postTranslate(parent.getScrollX(), parent.getScrollY()); 576e06b816e0ec64bac284d44c543166e88c9167889George Mount } 577333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount mSharedElementParentMatrices.add(matrix); 578333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 579333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 580333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount 581333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount private void getSharedElementParentMatrix(View view, Matrix matrix) { 58242161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount final int index = mSharedElementParentMatrices == null ? -1 58342161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount : mSharedElements.indexOf(view); 58442161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount if (index < 0) { 585333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount matrix.reset(); 586333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount ViewParent viewParent = view.getParent(); 587333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount if (viewParent instanceof ViewGroup) { 588333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount // Find the location in the view's parent 589333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount ViewGroup parent = (ViewGroup) viewParent; 590333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount parent.transformMatrixToLocal(matrix); 59118c2b0ef36400f4af6ee38dd84e2d65d18474b20Doris Liu matrix.postTranslate(parent.getScrollX(), parent.getScrollY()); 592333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 59342161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount } else { 59442161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount // The indices of mSharedElementParentMatrices matches the 59542161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount // mSharedElement matrices. 59642161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount Matrix parentMatrix = mSharedElementParentMatrices.get(index); 59742161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount matrix.set(parentMatrix); 598333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount } 599fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 600fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 601c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu protected ArrayList<SharedElementOriginalState> setSharedElementState( 602c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount Bundle sharedElementState, final ArrayList<View> snapshots) { 603c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu ArrayList<SharedElementOriginalState> originalImageState = 604c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu new ArrayList<SharedElementOriginalState>(); 605c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (sharedElementState != null) { 6067bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu Matrix tempMatrix = new Matrix(); 6077bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu RectF tempRect = new RectF(); 6081732f528952ea2df0bfd503fabb958af03dbfc81George Mount final int numSharedElements = mSharedElements.size(); 6091732f528952ea2df0bfd503fabb958af03dbfc81George Mount for (int i = 0; i < numSharedElements; i++) { 610c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount View sharedElement = mSharedElements.get(i); 611c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount String name = mSharedElementNames.get(i); 612c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu SharedElementOriginalState originalState = getOldSharedElementState(sharedElement, 613c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount name, sharedElementState); 614c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu originalImageState.add(originalState); 6157bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu setSharedElementState(sharedElement, name, sharedElementState, 6167bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu tempMatrix, tempRect, null); 617c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 618c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 6191732f528952ea2df0bfd503fabb958af03dbfc81George Mount if (mListener != null) { 6201732f528952ea2df0bfd503fabb958af03dbfc81George Mount mListener.onSharedElementStart(mSharedElementNames, mSharedElements, snapshots); 6211732f528952ea2df0bfd503fabb958af03dbfc81George Mount } 622fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount return originalImageState; 623fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 624fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 625fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount protected void notifySharedElementEnd(ArrayList<View> snapshots) { 6261732f528952ea2df0bfd503fabb958af03dbfc81George Mount if (mListener != null) { 6271732f528952ea2df0bfd503fabb958af03dbfc81George Mount mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, snapshots); 6281732f528952ea2df0bfd503fabb958af03dbfc81George Mount } 629fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 630c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 631fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount protected void scheduleSetSharedElementEnd(final ArrayList<View> snapshots) { 6326e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount final View decorView = getDecor(); 63348bd13c9cb2627847cf1f7707a084eb354e9c303George Mount if (decorView != null) { 634f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount OneShotPreDrawListener.add(decorView, () -> { 635f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount notifySharedElementEnd(snapshots); 636f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount }); 63748bd13c9cb2627847cf1f7707a084eb354e9c303George Mount } 638c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 639c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 640c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu private static SharedElementOriginalState getOldSharedElementState(View view, String name, 641c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount Bundle transitionArgs) { 642c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu 643c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu SharedElementOriginalState state = new SharedElementOriginalState(); 644c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu state.mLeft = view.getLeft(); 645c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu state.mTop = view.getTop(); 646c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu state.mRight = view.getRight(); 647c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu state.mBottom = view.getBottom(); 648c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu state.mMeasuredWidth = view.getMeasuredWidth(); 649c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu state.mMeasuredHeight = view.getMeasuredHeight(); 65026c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount state.mTranslationZ = view.getTranslationZ(); 65126c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount state.mElevation = view.getElevation(); 652c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (!(view instanceof ImageView)) { 653c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu return state; 654c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 655c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount Bundle bundle = transitionArgs.getBundle(name); 656c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (bundle == null) { 657c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu return state; 658c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 659c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount int scaleTypeInt = bundle.getInt(KEY_SCALE_TYPE, -1); 660c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (scaleTypeInt < 0) { 661c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu return state; 662c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 663c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 664c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount ImageView imageView = (ImageView) view; 665c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu state.mScaleType = imageView.getScaleType(); 666c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu if (state.mScaleType == ImageView.ScaleType.MATRIX) { 667c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu state.mMatrix = new Matrix(imageView.getImageMatrix()); 668c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 669c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu return state; 670c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 671c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 672c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount protected ArrayList<View> createSnapshots(Bundle state, Collection<String> names) { 673c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount int numSharedElements = names.size(); 6747c479f5a013fb5544be45cd3a952190fc3a923fcGeorge Mount ArrayList<View> snapshots = new ArrayList<View>(numSharedElements); 675c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (numSharedElements == 0) { 6767c479f5a013fb5544be45cd3a952190fc3a923fcGeorge Mount return snapshots; 677c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 678c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount Context context = getWindow().getContext(); 6797bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu int[] decorLoc = new int[2]; 68048bd13c9cb2627847cf1f7707a084eb354e9c303George Mount ViewGroup decorView = getDecor(); 68148bd13c9cb2627847cf1f7707a084eb354e9c303George Mount if (decorView != null) { 68248bd13c9cb2627847cf1f7707a084eb354e9c303George Mount decorView.getLocationOnScreen(decorLoc); 68348bd13c9cb2627847cf1f7707a084eb354e9c303George Mount } 684ca5094a05ce177c586f873ad556e7afc2656fe12George Mount Matrix tempMatrix = new Matrix(); 685c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount for (String name: names) { 686c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount Bundle sharedElementBundle = state.getBundle(name); 68792692c0284c2249e9a5381f7f19ec97f6b76d12fGeorge Mount View snapshot = null; 688c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (sharedElementBundle != null) { 689480ca829e2d3313740b4d14d30afbea6c98ff965George Mount Parcelable parcelable = sharedElementBundle.getParcelable(KEY_SNAPSHOT); 6901732f528952ea2df0bfd503fabb958af03dbfc81George Mount if (parcelable != null && mListener != null) { 6916558056e8fccc32f9e1dc59e46d09f8d916b7538George Mount snapshot = mListener.onCreateSnapshotView(context, parcelable); 692480ca829e2d3313740b4d14d30afbea6c98ff965George Mount } 693480ca829e2d3313740b4d14d30afbea6c98ff965George Mount if (snapshot != null) { 694ca5094a05ce177c586f873ad556e7afc2656fe12George Mount setSharedElementState(snapshot, name, state, tempMatrix, null, decorLoc); 695c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 696c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 69792692c0284c2249e9a5381f7f19ec97f6b76d12fGeorge Mount // Even null snapshots are added so they remain in the same order as shared elements. 69892692c0284c2249e9a5381f7f19ec97f6b76d12fGeorge Mount snapshots.add(snapshot); 699c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 700c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount return snapshots; 701c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 702c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 703c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu protected static void setOriginalSharedElementState(ArrayList<View> sharedElements, 704c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu ArrayList<SharedElementOriginalState> originalState) { 705c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount for (int i = 0; i < originalState.size(); i++) { 706c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu View view = sharedElements.get(i); 707c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu SharedElementOriginalState state = originalState.get(i); 708c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu if (view instanceof ImageView && state.mScaleType != null) { 709c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu ImageView imageView = (ImageView) view; 710c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu imageView.setScaleType(state.mScaleType); 711c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu if (state.mScaleType == ImageView.ScaleType.MATRIX) { 712c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu imageView.setImageMatrix(state.mMatrix); 713c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu } 714c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu } 71526c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount view.setElevation(state.mElevation); 71626c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount view.setTranslationZ(state.mTranslationZ); 71726c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount int widthSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredWidth, 718c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu View.MeasureSpec.EXACTLY); 719c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu int heightSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredHeight, 720c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu View.MeasureSpec.EXACTLY); 721c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu view.measure(widthSpec, heightSpec); 722c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu view.layout(state.mLeft, state.mTop, state.mRight, state.mBottom); 723c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 724c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 725c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 726c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount protected Bundle captureSharedElementState() { 727c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount Bundle bundle = new Bundle(); 7287bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu RectF tempBounds = new RectF(); 7297bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu Matrix tempMatrix = new Matrix(); 730f03c139018dd5b6f1ea53ac902caec7b6ee9ddd3Dake Gu for (int i = 0; i < mSharedElements.size(); i++) { 731c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount View sharedElement = mSharedElements.get(i); 732c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount String name = mSharedElementNames.get(i); 7337bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu captureSharedElementState(sharedElement, name, bundle, tempMatrix, tempBounds); 734c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 735c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount return bundle; 736c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 737c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 738a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount protected void clearState() { 739a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount // Clear the state so that we can't hold any references accidentally and leak memory. 740a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount mWindow = null; 741a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount mSharedElements.clear(); 742b694e080546316a27d22eba759027f6cb0a24705George Mount mTransitioningViews = null; 743aae763e692810fb411b83fdda57567e1b66577ddGeorge Mount mStrippedTransitioningViews = null; 7440f0c473488f8e8becc8883d3cdd9610324610dc4George Mount mOriginalAlphas.clear(); 745a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount mResultReceiver = null; 746a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount mPendingTransition = null; 747fc0fc0e341f2a2d707d5a8eafd65db34bdffb35cDake Gu mListener = null; 748333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount mSharedElementParentMatrices = null; 749a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount } 750a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount 751ed1e01d7e431edbcaab983b4b240418f2b090facGeorge Mount protected long getFadeDuration() { 752ed1e01d7e431edbcaab983b4b240418f2b090facGeorge Mount return getWindow().getTransitionBackgroundFadeDuration(); 753ed1e01d7e431edbcaab983b4b240418f2b090facGeorge Mount } 754ed1e01d7e431edbcaab983b4b240418f2b090facGeorge Mount 7550f0c473488f8e8becc8883d3cdd9610324610dc4George Mount protected void hideViews(ArrayList<View> views) { 756fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount int count = views.size(); 757fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount for (int i = 0; i < count; i++) { 7580f0c473488f8e8becc8883d3cdd9610324610dc4George Mount View view = views.get(i); 7590f0c473488f8e8becc8883d3cdd9610324610dc4George Mount if (!mOriginalAlphas.containsKey(view)) { 7600f0c473488f8e8becc8883d3cdd9610324610dc4George Mount mOriginalAlphas.put(view, view.getAlpha()); 7610f0c473488f8e8becc8883d3cdd9610324610dc4George Mount } 7620f0c473488f8e8becc8883d3cdd9610324610dc4George Mount view.setAlpha(0f); 7630f0c473488f8e8becc8883d3cdd9610324610dc4George Mount } 7640f0c473488f8e8becc8883d3cdd9610324610dc4George Mount } 7650f0c473488f8e8becc8883d3cdd9610324610dc4George Mount 766ce2ee3d6de670e52abed7f432778701113ba9c07George Mount protected void showViews(ArrayList<View> views, boolean setTransitionAlpha) { 7670f0c473488f8e8becc8883d3cdd9610324610dc4George Mount int count = views.size(); 7680f0c473488f8e8becc8883d3cdd9610324610dc4George Mount for (int i = 0; i < count; i++) { 769653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount showView(views.get(i), setTransitionAlpha); 770653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount } 771653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount } 772653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount 773653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount private void showView(View view, boolean setTransitionAlpha) { 774653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount Float alpha = mOriginalAlphas.remove(view); 775653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount if (alpha != null) { 776653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount view.setAlpha(alpha); 777653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount } 778653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount if (setTransitionAlpha) { 779653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount view.setTransitionAlpha(1f); 780b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount } 781b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount } 782b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount 783c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount /** 784c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount * Captures placement information for Views with a shared element name for 785c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount * Activity Transitions. 786c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount * 787c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount * @param view The View to capture the placement information for. 788c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount * @param name The shared element name in the target Activity to apply the placement 789c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount * information for. 790c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount * @param transitionArgs Bundle to store shared element placement information. 7918e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount * @param tempBounds A temporary Rect for capturing the current location of views. 792c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount */ 793480ca829e2d3313740b4d14d30afbea6c98ff965George Mount protected void captureSharedElementState(View view, String name, Bundle transitionArgs, 7947bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu Matrix tempMatrix, RectF tempBounds) { 795c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount Bundle sharedElementBundle = new Bundle(); 7967bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu tempMatrix.reset(); 7977bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu view.transformMatrixToGlobal(tempMatrix); 7988e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount tempBounds.set(0, 0, view.getWidth(), view.getHeight()); 7997bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu tempMatrix.mapRect(tempBounds); 800c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 8017bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu sharedElementBundle.putFloat(KEY_SCREEN_LEFT, tempBounds.left); 8027bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu sharedElementBundle.putFloat(KEY_SCREEN_RIGHT, tempBounds.right); 8037bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu sharedElementBundle.putFloat(KEY_SCREEN_TOP, tempBounds.top); 8047bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu sharedElementBundle.putFloat(KEY_SCREEN_BOTTOM, tempBounds.bottom); 805c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ()); 80626c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount sharedElementBundle.putFloat(KEY_ELEVATION, view.getElevation()); 807c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 8081732f528952ea2df0bfd503fabb958af03dbfc81George Mount Parcelable bitmap = null; 8091732f528952ea2df0bfd503fabb958af03dbfc81George Mount if (mListener != null) { 8101732f528952ea2df0bfd503fabb958af03dbfc81George Mount bitmap = mListener.onCaptureSharedElementSnapshot(view, tempMatrix, tempBounds); 8111732f528952ea2df0bfd503fabb958af03dbfc81George Mount } 8121732f528952ea2df0bfd503fabb958af03dbfc81George Mount 813480ca829e2d3313740b4d14d30afbea6c98ff965George Mount if (bitmap != null) { 814480ca829e2d3313740b4d14d30afbea6c98ff965George Mount sharedElementBundle.putParcelable(KEY_SNAPSHOT, bitmap); 815c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 816c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 817c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (view instanceof ImageView) { 818c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount ImageView imageView = (ImageView) view; 819c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount int scaleTypeInt = scaleTypeToInt(imageView.getScaleType()); 820c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount sharedElementBundle.putInt(KEY_SCALE_TYPE, scaleTypeInt); 821c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (imageView.getScaleType() == ImageView.ScaleType.MATRIX) { 822c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount float[] matrix = new float[9]; 823c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount imageView.getImageMatrix().getValues(matrix); 824c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount sharedElementBundle.putFloatArray(KEY_IMAGE_MATRIX, matrix); 825c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 826c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 827c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 828c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount transitionArgs.putBundle(name, sharedElementBundle); 829c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 830c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 83167d924341a1d0994ac68b3b7898d5576edd987b4George Mount 83267d924341a1d0994ac68b3b7898d5576edd987b4George Mount protected void startTransition(Runnable runnable) { 83367d924341a1d0994ac68b3b7898d5576edd987b4George Mount if (mIsStartingTransition) { 83467d924341a1d0994ac68b3b7898d5576edd987b4George Mount mPendingTransition = runnable; 83567d924341a1d0994ac68b3b7898d5576edd987b4George Mount } else { 83667d924341a1d0994ac68b3b7898d5576edd987b4George Mount mIsStartingTransition = true; 83767d924341a1d0994ac68b3b7898d5576edd987b4George Mount runnable.run(); 83867d924341a1d0994ac68b3b7898d5576edd987b4George Mount } 83967d924341a1d0994ac68b3b7898d5576edd987b4George Mount } 84067d924341a1d0994ac68b3b7898d5576edd987b4George Mount 84113ccb79b34f6db1580714ea980c8490121d7e5aeGeorge Mount protected void transitionStarted() { 84213ccb79b34f6db1580714ea980c8490121d7e5aeGeorge Mount mIsStartingTransition = false; 84313ccb79b34f6db1580714ea980c8490121d7e5aeGeorge Mount } 84413ccb79b34f6db1580714ea980c8490121d7e5aeGeorge Mount 845fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount /** 846fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount * Cancels any pending transitions and returns true if there is a transition is in 847fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount * the middle of starting. 848fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount */ 849fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount protected boolean cancelPendingTransitions() { 850fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount mPendingTransition = null; 851fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount return mIsStartingTransition; 852fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount } 853fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount 854fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount protected void moveSharedElementsToOverlay() { 855eca1ae5e442bf5f13617ab823343730619512632George Mount if (mWindow == null || !mWindow.getSharedElementsUseOverlay()) { 856b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount return; 857b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount } 858333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount setSharedElementMatrices(); 859fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount int numSharedElements = mSharedElements.size(); 860fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount ViewGroup decor = getDecor(); 861fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount if (decor != null) { 862fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount boolean moveWithParent = moveSharedElementWithParent(); 86342161c5cb4f5f36cf83c8af3f20db70a70850a88George Mount Matrix tempMatrix = new Matrix(); 864fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount for (int i = 0; i < numSharedElements; i++) { 865fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount View view = mSharedElements.get(i); 866e06b816e0ec64bac284d44c543166e88c9167889George Mount if (view.isAttachedToWindow()) { 867e06b816e0ec64bac284d44c543166e88c9167889George Mount tempMatrix.reset(); 868e06b816e0ec64bac284d44c543166e88c9167889George Mount mSharedElementParentMatrices.get(i).invert(tempMatrix); 869e06b816e0ec64bac284d44c543166e88c9167889George Mount GhostView.addGhost(view, decor, tempMatrix); 870e06b816e0ec64bac284d44c543166e88c9167889George Mount ViewGroup parent = (ViewGroup) view.getParent(); 871e06b816e0ec64bac284d44c543166e88c9167889George Mount if (moveWithParent && !isInTransitionGroup(parent, decor)) { 872e06b816e0ec64bac284d44c543166e88c9167889George Mount GhostViewListeners listener = new GhostViewListeners(view, parent, decor); 873e06b816e0ec64bac284d44c543166e88c9167889George Mount parent.getViewTreeObserver().addOnPreDrawListener(listener); 874e06b816e0ec64bac284d44c543166e88c9167889George Mount parent.addOnAttachStateChangeListener(listener); 875e06b816e0ec64bac284d44c543166e88c9167889George Mount mGhostViewListeners.add(listener); 876e06b816e0ec64bac284d44c543166e88c9167889George Mount } 877fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 878fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 879fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 880fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 881fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 882fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount protected boolean moveSharedElementWithParent() { 883fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount return true; 884fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 885fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 886fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount public static boolean isInTransitionGroup(ViewParent viewParent, ViewGroup decor) { 887fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount if (viewParent == decor || !(viewParent instanceof ViewGroup)) { 888fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount return false; 889fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 890fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount ViewGroup parent = (ViewGroup) viewParent; 891fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount if (parent.isTransitionGroup()) { 892fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount return true; 893fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } else { 894fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount return isInTransitionGroup(parent.getParent(), decor); 895fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 896fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 897fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 898fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount protected void moveSharedElementsFromOverlay() { 899b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount int numListeners = mGhostViewListeners.size(); 900b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount for (int i = 0; i < numListeners; i++) { 901b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount GhostViewListeners listener = mGhostViewListeners.get(i); 902f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount listener.removeListener(); 903b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount } 904b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount mGhostViewListeners.clear(); 905b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount 906b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount if (mWindow == null || !mWindow.getSharedElementsUseOverlay()) { 907b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount return; 908b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount } 909fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount ViewGroup decor = getDecor(); 910fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount if (decor != null) { 911fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount ViewGroupOverlay overlay = decor.getOverlay(); 912fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount int count = mSharedElements.size(); 913fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount for (int i = 0; i < count; i++) { 914fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount View sharedElement = mSharedElements.get(i); 915fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount GhostView.removeGhost(sharedElement); 916fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 917fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 918fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 919fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 920fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount protected void setGhostVisibility(int visibility) { 921fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount int numSharedElements = mSharedElements.size(); 922fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount for (int i = 0; i < numSharedElements; i++) { 923fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount GhostView ghostView = GhostView.getGhost(mSharedElements.get(i)); 924fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount if (ghostView != null) { 925fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount ghostView.setVisibility(visibility); 926fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 927fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 928fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 929fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 930fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount protected void scheduleGhostVisibilityChange(final int visibility) { 9316e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount final View decorView = getDecor(); 93248bd13c9cb2627847cf1f7707a084eb354e9c303George Mount if (decorView != null) { 933f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount OneShotPreDrawListener.add(decorView, () -> { 934f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount setGhostVisibility(visibility); 935f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount }); 93648bd13c9cb2627847cf1f7707a084eb354e9c303George Mount } 937fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 938fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 93941725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount protected boolean isViewsTransitionComplete() { 94041725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount return mViewsTransitionComplete; 94141725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount } 94241725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount 94341725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount protected void viewsTransitionComplete() { 94441725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount mViewsTransitionComplete = true; 94541725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount startInputWhenTransitionsComplete(); 94641725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount } 94741725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount 948b64e777f6c14d862f221f4da814079df22663db1Chet Haase protected void backgroundAnimatorComplete() { 949b64e777f6c14d862f221f4da814079df22663db1Chet Haase mBackgroundAnimatorComplete = true; 950b64e777f6c14d862f221f4da814079df22663db1Chet Haase } 951b64e777f6c14d862f221f4da814079df22663db1Chet Haase 95241725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount protected void sharedElementTransitionComplete() { 95341725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount mSharedElementTransitionComplete = true; 95441725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount startInputWhenTransitionsComplete(); 95541725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount } 95641725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount private void startInputWhenTransitionsComplete() { 95741725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount if (mViewsTransitionComplete && mSharedElementTransitionComplete) { 95841725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount final View decor = getDecor(); 95941725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount if (decor != null) { 96041725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount final ViewRootImpl viewRoot = decor.getViewRootImpl(); 9615fddd4ca581aeb7c6b526628cfbf7915a2e20574George Mount if (viewRoot != null) { 9625fddd4ca581aeb7c6b526628cfbf7915a2e20574George Mount viewRoot.setPausedForTransition(false); 9635fddd4ca581aeb7c6b526628cfbf7915a2e20574George Mount } 96441725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount } 96541725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount onTransitionsComplete(); 96641725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount } 96741725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount } 96841725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount 96980141d1c8b799cf7669a29b8837037cf3934ddb9George Mount protected void pauseInput() { 97080141d1c8b799cf7669a29b8837037cf3934ddb9George Mount final View decor = getDecor(); 97180141d1c8b799cf7669a29b8837037cf3934ddb9George Mount final ViewRootImpl viewRoot = decor == null ? null : decor.getViewRootImpl(); 97280141d1c8b799cf7669a29b8837037cf3934ddb9George Mount if (viewRoot != null) { 97380141d1c8b799cf7669a29b8837037cf3934ddb9George Mount viewRoot.setPausedForTransition(true); 97480141d1c8b799cf7669a29b8837037cf3934ddb9George Mount } 97580141d1c8b799cf7669a29b8837037cf3934ddb9George Mount } 97680141d1c8b799cf7669a29b8837037cf3934ddb9George Mount 97741725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount protected void onTransitionsComplete() {} 97841725dedc33906aaafee36b2d6523596e2a8a52eGeorge Mount 979e0c37bdea37f78778f6c4f23f03604e59dfb0d55Ben Weiss protected class ContinueTransitionListener extends TransitionListenerAdapter { 98067d924341a1d0994ac68b3b7898d5576edd987b4George Mount @Override 98167d924341a1d0994ac68b3b7898d5576edd987b4George Mount public void onTransitionStart(Transition transition) { 98267d924341a1d0994ac68b3b7898d5576edd987b4George Mount mIsStartingTransition = false; 98367d924341a1d0994ac68b3b7898d5576edd987b4George Mount Runnable pending = mPendingTransition; 98467d924341a1d0994ac68b3b7898d5576edd987b4George Mount mPendingTransition = null; 98567d924341a1d0994ac68b3b7898d5576edd987b4George Mount if (pending != null) { 98667d924341a1d0994ac68b3b7898d5576edd987b4George Mount startTransition(pending); 98767d924341a1d0994ac68b3b7898d5576edd987b4George Mount } 98867d924341a1d0994ac68b3b7898d5576edd987b4George Mount } 98925f98a4c0156ec40d1d92cfe5a24459d9ffa6f91George Mount 99025f98a4c0156ec40d1d92cfe5a24459d9ffa6f91George Mount @Override 99125f98a4c0156ec40d1d92cfe5a24459d9ffa6f91George Mount public void onTransitionEnd(Transition transition) { 99225f98a4c0156ec40d1d92cfe5a24459d9ffa6f91George Mount transition.removeListener(this); 99325f98a4c0156ec40d1d92cfe5a24459d9ffa6f91George Mount } 99467d924341a1d0994ac68b3b7898d5576edd987b4George Mount } 99567d924341a1d0994ac68b3b7898d5576edd987b4George Mount 996c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount private static int scaleTypeToInt(ImageView.ScaleType scaleType) { 997c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount for (int i = 0; i < SCALE_TYPE_VALUES.length; i++) { 998c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount if (scaleType == SCALE_TYPE_VALUES[i]) { 999c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount return i; 1000c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 1001c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 1002c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount return -1; 1003c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount } 1004c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount 1005629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount protected void setTransitioningViewsVisiblity(int visiblity, boolean invalidate) { 1006629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount final int numElements = mTransitioningViews == null ? 0 : mTransitioningViews.size(); 1007629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount for (int i = 0; i < numElements; i++) { 1008629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount final View view = mTransitioningViews.get(i); 1009629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount view.setTransitionVisibility(visiblity); 1010629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount if (invalidate) { 1011629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount view.invalidate(); 1012629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount } 1013629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount } 1014629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount } 1015629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount 10161349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount /** 10171349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount * Blocks suppressLayout from Visibility transitions. It is ok to suppress the layout, 10181349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount * but we don't want to force the layout when suppressLayout becomes false. This leads 10191349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount * to visual glitches. 10201349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount */ 10211349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount private static void noLayoutSuppressionForVisibilityTransitions(Transition transition) { 10221349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount if (transition instanceof Visibility) { 10231349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount final Visibility visibility = (Visibility) transition; 10241349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount visibility.setSuppressLayout(false); 10251349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount } else if (transition instanceof TransitionSet) { 10261349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount final TransitionSet set = (TransitionSet) transition; 10271349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount final int count = set.getTransitionCount(); 10281349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount for (int i = 0; i < count; i++) { 10291349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount noLayoutSuppressionForVisibilityTransitions(set.getTransitionAt(i)); 10301349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount } 10311349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount } 10321349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount } 10331349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount 1034b64e777f6c14d862f221f4da814079df22663db1Chet Haase public boolean isTransitionRunning() { 1035b64e777f6c14d862f221f4da814079df22663db1Chet Haase return !(mViewsTransitionComplete && mSharedElementTransitionComplete && 1036b64e777f6c14d862f221f4da814079df22663db1Chet Haase mBackgroundAnimatorComplete); 1037b64e777f6c14d862f221f4da814079df22663db1Chet Haase } 1038b64e777f6c14d862f221f4da814079df22663db1Chet Haase 103931a217290cf376d0573fc36e21c8940987485019George Mount private static class FixedEpicenterCallback extends Transition.EpicenterCallback { 104031a217290cf376d0573fc36e21c8940987485019George Mount private Rect mEpicenter; 104131a217290cf376d0573fc36e21c8940987485019George Mount 104231a217290cf376d0573fc36e21c8940987485019George Mount public void setEpicenter(Rect epicenter) { mEpicenter = epicenter; } 104331a217290cf376d0573fc36e21c8940987485019George Mount 104431a217290cf376d0573fc36e21c8940987485019George Mount @Override 1045dc21d3b2804c24fe29ec860796d11185901364c4George Mount public Rect onGetEpicenter(Transition transition) { 104631a217290cf376d0573fc36e21c8940987485019George Mount return mEpicenter; 104731a217290cf376d0573fc36e21c8940987485019George Mount } 104831a217290cf376d0573fc36e21c8940987485019George Mount } 1049800d72b0e05049e4a8f90ea96ec165fc975264ceGeorge Mount 1050f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount private static class GhostViewListeners implements ViewTreeObserver.OnPreDrawListener, 1051f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount View.OnAttachStateChangeListener { 1052fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount private View mView; 1053fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount private ViewGroup mDecor; 10546e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount private View mParent; 1055fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount private Matrix mMatrix = new Matrix(); 1056f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount private ViewTreeObserver mViewTreeObserver; 1057fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 10586e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount public GhostViewListeners(View view, View parent, ViewGroup decor) { 1059fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount mView = view; 10606e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount mParent = parent; 1061fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount mDecor = decor; 1062f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount mViewTreeObserver = parent.getViewTreeObserver(); 1063fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 1064fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 1065fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount public View getView() { 1066fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount return mView; 1067fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 1068fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 1069fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount @Override 1070fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount public boolean onPreDraw() { 1071fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount GhostView ghostView = GhostView.getGhost(mView); 1072e06b816e0ec64bac284d44c543166e88c9167889George Mount if (ghostView == null || !mView.isAttachedToWindow()) { 1073f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount removeListener(); 1074fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } else { 1075fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount GhostView.calculateMatrix(mView, mDecor, mMatrix); 1076fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount ghostView.setMatrix(mMatrix); 1077fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 1078fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount return true; 1079fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 1080f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount 1081f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount public void removeListener() { 1082f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount if (mViewTreeObserver.isAlive()) { 1083f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount mViewTreeObserver.removeOnPreDrawListener(this); 1084f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount } else { 1085f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount mParent.getViewTreeObserver().removeOnPreDrawListener(this); 1086f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount } 1087f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount mParent.removeOnAttachStateChangeListener(this); 1088f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount } 1089f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount 1090f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount @Override 1091f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount public void onViewAttachedToWindow(View v) { 1092f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount mViewTreeObserver = v.getViewTreeObserver(); 1093f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount } 1094f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount 1095f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount @Override 1096f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount public void onViewDetachedFromWindow(View v) { 1097f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount removeListener(); 1098f0b46b9540b48448c1f1fbe55ca2930770bd72e2George Mount } 1099fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount } 1100fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount 1101c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu static class SharedElementOriginalState { 1102c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu int mLeft; 1103c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu int mTop; 1104c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu int mRight; 1105c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu int mBottom; 1106c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu int mMeasuredWidth; 1107c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu int mMeasuredHeight; 1108c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu ImageView.ScaleType mScaleType; 1109c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu Matrix mMatrix; 111026c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount float mTranslationZ; 111126c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount float mElevation; 1112c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu } 111331a217290cf376d0573fc36e21c8940987485019George Mount} 1114