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;
2731a217290cf376d0573fc36e21c8940987485019George Mountimport android.transition.TransitionSet;
2831a217290cf376d0573fc36e21c8940987485019George Mountimport android.util.ArrayMap;
29fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mountimport android.view.GhostView;
3031a217290cf376d0573fc36e21c8940987485019George Mountimport android.view.View;
3131a217290cf376d0573fc36e21c8940987485019George Mountimport android.view.ViewGroup;
32fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mountimport android.view.ViewGroupOverlay;
33fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mountimport android.view.ViewParent;
34c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mountimport android.view.ViewTreeObserver;
3531a217290cf376d0573fc36e21c8940987485019George Mountimport android.view.Window;
36caa03107d4322b0e30f92e6dc1eb1ea73b1bf747George Mountimport android.widget.ImageView;
3731a217290cf376d0573fc36e21c8940987485019George Mount
3831a217290cf376d0573fc36e21c8940987485019George Mountimport java.util.ArrayList;
3931a217290cf376d0573fc36e21c8940987485019George Mountimport java.util.Collection;
4031a217290cf376d0573fc36e21c8940987485019George Mount
4131a217290cf376d0573fc36e21c8940987485019George Mount/**
4231a217290cf376d0573fc36e21c8940987485019George Mount * Base class for ExitTransitionCoordinator and EnterTransitionCoordinator, classes
4331a217290cf376d0573fc36e21c8940987485019George Mount * that manage activity transitions and the communications coordinating them between
4431a217290cf376d0573fc36e21c8940987485019George Mount * Activities. The ExitTransitionCoordinator is created in the
4531a217290cf376d0573fc36e21c8940987485019George Mount * ActivityOptions#makeSceneTransitionAnimation. The EnterTransitionCoordinator
4631a217290cf376d0573fc36e21c8940987485019George Mount * is created by ActivityOptions#createEnterActivityTransition by Activity when the window is
4731a217290cf376d0573fc36e21c8940987485019George Mount * attached.
4831a217290cf376d0573fc36e21c8940987485019George Mount *
4931a217290cf376d0573fc36e21c8940987485019George Mount * Typical startActivity goes like this:
5031a217290cf376d0573fc36e21c8940987485019George Mount * 1) ExitTransitionCoordinator created with ActivityOptions#makeSceneTransitionAnimation
5131a217290cf376d0573fc36e21c8940987485019George Mount * 2) Activity#startActivity called and that calls startExit() through
5231a217290cf376d0573fc36e21c8940987485019George Mount *    ActivityOptions#dispatchStartExit
5331a217290cf376d0573fc36e21c8940987485019George Mount *    - Exit transition starts by setting transitioning Views to INVISIBLE
5431a217290cf376d0573fc36e21c8940987485019George Mount * 3) Launched Activity starts, creating an EnterTransitionCoordinator.
5531a217290cf376d0573fc36e21c8940987485019George Mount *    - The Window is made translucent
5631a217290cf376d0573fc36e21c8940987485019George Mount *    - The Window background alpha is set to 0
5731a217290cf376d0573fc36e21c8940987485019George Mount *    - The transitioning views are made INVISIBLE
5831a217290cf376d0573fc36e21c8940987485019George Mount *    - MSG_SET_LISTENER is sent back to the ExitTransitionCoordinator.
5931a217290cf376d0573fc36e21c8940987485019George Mount * 4) The shared element transition completes.
6031a217290cf376d0573fc36e21c8940987485019George Mount *    - MSG_TAKE_SHARED_ELEMENTS is sent to the EnterTransitionCoordinator
6131a217290cf376d0573fc36e21c8940987485019George Mount * 5) The MSG_TAKE_SHARED_ELEMENTS is received by the EnterTransitionCoordinator.
6231a217290cf376d0573fc36e21c8940987485019George Mount *    - Shared elements are made VISIBLE
6331a217290cf376d0573fc36e21c8940987485019George Mount *    - Shared elements positions and size are set to match the end state of the calling
6431a217290cf376d0573fc36e21c8940987485019George Mount *      Activity.
6531a217290cf376d0573fc36e21c8940987485019George Mount *    - The shared element transition is started
6631a217290cf376d0573fc36e21c8940987485019George Mount *    - If the window allows overlapping transitions, the views transition is started by setting
6731a217290cf376d0573fc36e21c8940987485019George Mount *      the entering Views to VISIBLE and the background alpha is animated to opaque.
6831a217290cf376d0573fc36e21c8940987485019George Mount *    - MSG_HIDE_SHARED_ELEMENTS is sent to the ExitTransitionCoordinator
6931a217290cf376d0573fc36e21c8940987485019George Mount * 6) MSG_HIDE_SHARED_ELEMENTS is received by the ExitTransitionCoordinator
7031a217290cf376d0573fc36e21c8940987485019George Mount *    - The shared elements are made INVISIBLE
7131a217290cf376d0573fc36e21c8940987485019George Mount * 7) The exit transition completes in the calling Activity.
7231a217290cf376d0573fc36e21c8940987485019George Mount *    - MSG_EXIT_TRANSITION_COMPLETE is sent to the EnterTransitionCoordinator.
7331a217290cf376d0573fc36e21c8940987485019George Mount * 8) The MSG_EXIT_TRANSITION_COMPLETE is received by the EnterTransitionCoordinator.
7431a217290cf376d0573fc36e21c8940987485019George Mount *    - If the window doesn't allow overlapping enter transitions, the enter transition is started
7531a217290cf376d0573fc36e21c8940987485019George Mount *      by setting entering views to VISIBLE and the background is animated to opaque.
7631a217290cf376d0573fc36e21c8940987485019George Mount * 9) The background opacity animation completes.
7731a217290cf376d0573fc36e21c8940987485019George Mount *    - The window is made opaque
7831a217290cf376d0573fc36e21c8940987485019George Mount * 10) The calling Activity gets an onStop() call
7931a217290cf376d0573fc36e21c8940987485019George Mount *    - onActivityStopped() is called and all exited Views are made VISIBLE.
8031a217290cf376d0573fc36e21c8940987485019George Mount *
8173f843de4b65772c624ca8ebb8c976a279e37ce9Craig Mautner * Typical finishAfterTransition goes like this:
8273f843de4b65772c624ca8ebb8c976a279e37ce9Craig Mautner * 1) finishAfterTransition() creates an ExitTransitionCoordinator and calls startExit()
8362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount *    - The Window start transitioning to Translucent with a new ActivityOptions.
8431a217290cf376d0573fc36e21c8940987485019George Mount *    - If no background exists, a black background is substituted
8531a217290cf376d0573fc36e21c8940987485019George Mount *    - The shared elements in the scene are matched against those shared elements
8631a217290cf376d0573fc36e21c8940987485019George Mount *      that were sent by comparing the names.
8731a217290cf376d0573fc36e21c8940987485019George Mount *    - The exit transition is started by setting Views to INVISIBLE.
8862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * 2) The ActivityOptions is received by the Activity and an EnterTransitionCoordinator is created.
8931a217290cf376d0573fc36e21c8940987485019George Mount *    - All transitioning views are made VISIBLE to reverse what was done when onActivityStopped()
9031a217290cf376d0573fc36e21c8940987485019George Mount *      was called
9131a217290cf376d0573fc36e21c8940987485019George Mount * 3) The Window is made translucent and a callback is received
9231a217290cf376d0573fc36e21c8940987485019George Mount *    - The background alpha is animated to 0
9331a217290cf376d0573fc36e21c8940987485019George Mount * 4) The background alpha animation completes
9431a217290cf376d0573fc36e21c8940987485019George Mount * 5) The shared element transition completes
9531a217290cf376d0573fc36e21c8940987485019George Mount *    - After both 4 & 5 complete, MSG_TAKE_SHARED_ELEMENTS is sent to the
9662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount *      EnterTransitionCoordinator
9762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * 6) MSG_TAKE_SHARED_ELEMENTS is received by EnterTransitionCoordinator
9831a217290cf376d0573fc36e21c8940987485019George Mount *    - Shared elements are made VISIBLE
9931a217290cf376d0573fc36e21c8940987485019George Mount *    - Shared elements positions and size are set to match the end state of the calling
10031a217290cf376d0573fc36e21c8940987485019George Mount *      Activity.
10131a217290cf376d0573fc36e21c8940987485019George Mount *    - The shared element transition is started
10231a217290cf376d0573fc36e21c8940987485019George Mount *    - If the window allows overlapping transitions, the views transition is started by setting
10331a217290cf376d0573fc36e21c8940987485019George Mount *      the entering Views to VISIBLE.
10462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount *    - MSG_HIDE_SHARED_ELEMENTS is sent to the ExitTransitionCoordinator
10562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * 7) MSG_HIDE_SHARED_ELEMENTS is received by the ExitTransitionCoordinator
10631a217290cf376d0573fc36e21c8940987485019George Mount *    - The shared elements are made INVISIBLE
10731a217290cf376d0573fc36e21c8940987485019George Mount * 8) The exit transition completes in the finishing Activity.
10862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount *    - MSG_EXIT_TRANSITION_COMPLETE is sent to the EnterTransitionCoordinator.
10931a217290cf376d0573fc36e21c8940987485019George Mount *    - finish() is called on the exiting Activity
11062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount * 9) The MSG_EXIT_TRANSITION_COMPLETE is received by the EnterTransitionCoordinator.
11131a217290cf376d0573fc36e21c8940987485019George Mount *    - If the window doesn't allow overlapping enter transitions, the enter transition is started
11231a217290cf376d0573fc36e21c8940987485019George Mount *      by setting entering views to VISIBLE.
11331a217290cf376d0573fc36e21c8940987485019George Mount */
11431a217290cf376d0573fc36e21c8940987485019George Mountabstract class ActivityTransitionCoordinator extends ResultReceiver {
11531a217290cf376d0573fc36e21c8940987485019George Mount    private static final String TAG = "ActivityTransitionCoordinator";
11631a217290cf376d0573fc36e21c8940987485019George Mount
11731a217290cf376d0573fc36e21c8940987485019George Mount    /**
11831a217290cf376d0573fc36e21c8940987485019George Mount     * For Activity transitions, the called Activity's listener to receive calls
11931a217290cf376d0573fc36e21c8940987485019George Mount     * when transitions complete.
12031a217290cf376d0573fc36e21c8940987485019George Mount     */
12162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    static final String KEY_REMOTE_RECEIVER = "android:remoteReceiver";
12262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount
1237bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu    protected static final String KEY_SCREEN_LEFT = "shared_element:screenLeft";
1247bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu    protected static final String KEY_SCREEN_TOP = "shared_element:screenTop";
1257bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu    protected static final String KEY_SCREEN_RIGHT = "shared_element:screenRight";
1267bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu    protected static final String KEY_SCREEN_BOTTOM= "shared_element:screenBottom";
12762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static final String KEY_TRANSLATION_Z = "shared_element:translationZ";
128480ca829e2d3313740b4d14d30afbea6c98ff965George Mount    protected static final String KEY_SNAPSHOT = "shared_element:bitmap";
12962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static final String KEY_SCALE_TYPE = "shared_element:scaleType";
13062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static final String KEY_IMAGE_MATRIX = "shared_element:imageMatrix";
13126c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount    protected static final String KEY_ELEVATION = "shared_element:elevation";
13231a217290cf376d0573fc36e21c8940987485019George Mount
13362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static final ImageView.ScaleType[] SCALE_TYPE_VALUES = ImageView.ScaleType.values();
13431a217290cf376d0573fc36e21c8940987485019George Mount
13531a217290cf376d0573fc36e21c8940987485019George Mount    /**
13631a217290cf376d0573fc36e21c8940987485019George Mount     * Sent by the exiting coordinator (either EnterTransitionCoordinator
13731a217290cf376d0573fc36e21c8940987485019George Mount     * or ExitTransitionCoordinator) after the shared elements have
13831a217290cf376d0573fc36e21c8940987485019George Mount     * become stationary (shared element transition completes). This tells
13931a217290cf376d0573fc36e21c8940987485019George Mount     * the remote coordinator to take control of the shared elements and
14031a217290cf376d0573fc36e21c8940987485019George Mount     * that animations may begin. The remote Activity won't start entering
14131a217290cf376d0573fc36e21c8940987485019George Mount     * until this message is received, but may wait for
14231a217290cf376d0573fc36e21c8940987485019George Mount     * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true.
14331a217290cf376d0573fc36e21c8940987485019George Mount     */
14462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public static final int MSG_SET_REMOTE_RECEIVER = 100;
14531a217290cf376d0573fc36e21c8940987485019George Mount
14631a217290cf376d0573fc36e21c8940987485019George Mount    /**
14731a217290cf376d0573fc36e21c8940987485019George Mount     * Sent by the entering coordinator to tell the exiting coordinator
14831a217290cf376d0573fc36e21c8940987485019George Mount     * to hide its shared elements after it has started its shared
14931a217290cf376d0573fc36e21c8940987485019George Mount     * element transition. This is temporary until the
15031a217290cf376d0573fc36e21c8940987485019George Mount     * interlock of shared elements is figured out.
15131a217290cf376d0573fc36e21c8940987485019George Mount     */
15231a217290cf376d0573fc36e21c8940987485019George Mount    public static final int MSG_HIDE_SHARED_ELEMENTS = 101;
15331a217290cf376d0573fc36e21c8940987485019George Mount
15431a217290cf376d0573fc36e21c8940987485019George Mount    /**
15531a217290cf376d0573fc36e21c8940987485019George Mount     * Sent by the exiting coordinator (either EnterTransitionCoordinator
15631a217290cf376d0573fc36e21c8940987485019George Mount     * or ExitTransitionCoordinator) after the shared elements have
15731a217290cf376d0573fc36e21c8940987485019George Mount     * become stationary (shared element transition completes). This tells
15831a217290cf376d0573fc36e21c8940987485019George Mount     * the remote coordinator to take control of the shared elements and
15931a217290cf376d0573fc36e21c8940987485019George Mount     * that animations may begin. The remote Activity won't start entering
16031a217290cf376d0573fc36e21c8940987485019George Mount     * until this message is received, but may wait for
16131a217290cf376d0573fc36e21c8940987485019George Mount     * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true.
16231a217290cf376d0573fc36e21c8940987485019George Mount     */
16362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public static final int MSG_TAKE_SHARED_ELEMENTS = 103;
16431a217290cf376d0573fc36e21c8940987485019George Mount
16531a217290cf376d0573fc36e21c8940987485019George Mount    /**
16631a217290cf376d0573fc36e21c8940987485019George Mount     * Sent by the exiting coordinator (either
16731a217290cf376d0573fc36e21c8940987485019George Mount     * EnterTransitionCoordinator or ExitTransitionCoordinator) after
16831a217290cf376d0573fc36e21c8940987485019George Mount     * the exiting Views have finished leaving the scene. This will
16931a217290cf376d0573fc36e21c8940987485019George Mount     * be ignored if allowOverlappingTransitions() is true on the
17031a217290cf376d0573fc36e21c8940987485019George Mount     * remote coordinator. If it is false, it will trigger the enter
17131a217290cf376d0573fc36e21c8940987485019George Mount     * transition to start.
17231a217290cf376d0573fc36e21c8940987485019George Mount     */
17362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public static final int MSG_EXIT_TRANSITION_COMPLETE = 104;
17431a217290cf376d0573fc36e21c8940987485019George Mount
17531a217290cf376d0573fc36e21c8940987485019George Mount    /**
17631a217290cf376d0573fc36e21c8940987485019George Mount     * Sent by Activity#startActivity to begin the exit transition.
17731a217290cf376d0573fc36e21c8940987485019George Mount     */
17862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public static final int MSG_START_EXIT_TRANSITION = 105;
17931a217290cf376d0573fc36e21c8940987485019George Mount
18031a217290cf376d0573fc36e21c8940987485019George Mount    /**
18162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount     * It took too long for a message from the entering Activity, so we canceled the transition.
18231a217290cf376d0573fc36e21c8940987485019George Mount     */
18362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public static final int MSG_CANCEL = 106;
18462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount
185c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    /**
186c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * When returning, this is the destination location for the shared element.
187c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     */
188c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    public static final int MSG_SHARED_ELEMENT_DESTINATION = 107;
189c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
190d265bd7446e662c9597226c596e8f91eda824982George Mount    /**
191d265bd7446e662c9597226c596e8f91eda824982George Mount     * Send the shared element positions.
192d265bd7446e662c9597226c596e8f91eda824982George Mount     */
193d265bd7446e662c9597226c596e8f91eda824982George Mount    public static final int MSG_SEND_SHARED_ELEMENT_DESTINATION = 108;
194d265bd7446e662c9597226c596e8f91eda824982George Mount
195a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount    private Window mWindow;
19662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    final protected ArrayList<String> mAllSharedElementNames;
19762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    final protected ArrayList<View> mSharedElements = new ArrayList<View>();
19862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    final protected ArrayList<String> mSharedElementNames = new ArrayList<String>();
199b694e080546316a27d22eba759027f6cb0a24705George Mount    protected ArrayList<View> mTransitioningViews = new ArrayList<View>();
2006558056e8fccc32f9e1dc59e46d09f8d916b7538George Mount    protected SharedElementCallback mListener;
20162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected ResultReceiver mResultReceiver;
20262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    final private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback();
203c9b6df8fa4df3968b2420a52c5281b4765478f68George Mount    final protected boolean mIsReturning;
20467d924341a1d0994ac68b3b7898d5576edd987b4George Mount    private Runnable mPendingTransition;
20567d924341a1d0994ac68b3b7898d5576edd987b4George Mount    private boolean mIsStartingTransition;
206fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    private ArrayList<GhostViewListeners> mGhostViewListeners =
207fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            new ArrayList<GhostViewListeners>();
2080f0c473488f8e8becc8883d3cdd9610324610dc4George Mount    private ArrayMap<View, Float> mOriginalAlphas = new ArrayMap<View, Float>();
209333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount    final private ArrayList<View> mRootSharedElements = new ArrayList<View>();
210333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount    private ArrayList<Matrix> mSharedElementParentMatrices;
21167d924341a1d0994ac68b3b7898d5576edd987b4George Mount
2128c2614ce4328640642d8e8be437859e0508a39b4George Mount    public ActivityTransitionCoordinator(Window window,
2138c2614ce4328640642d8e8be437859e0508a39b4George Mount            ArrayList<String> allSharedElementNames,
2146558056e8fccc32f9e1dc59e46d09f8d916b7538George Mount            SharedElementCallback listener, boolean isReturning) {
21562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        super(new Handler());
21662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        mWindow = window;
21762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        mListener = listener;
21862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        mAllSharedElementNames = allSharedElementNames;
219c9b6df8fa4df3968b2420a52c5281b4765478f68George Mount        mIsReturning = isReturning;
2208c2614ce4328640642d8e8be437859e0508a39b4George Mount    }
2218c2614ce4328640642d8e8be437859e0508a39b4George Mount
2221fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount    protected void viewsReady(ArrayMap<String, View> sharedElements) {
223ce725a47f6eee75a6ef86397e9b9fe471aeb1f84George Mount        sharedElements.retainAll(mAllSharedElementNames);
2241732f528952ea2df0bfd503fabb958af03dbfc81George Mount        if (mListener != null) {
2251732f528952ea2df0bfd503fabb958af03dbfc81George Mount            mListener.onMapSharedElements(mAllSharedElementNames, sharedElements);
2261732f528952ea2df0bfd503fabb958af03dbfc81George Mount        }
227333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        setSharedElements(sharedElements);
228b694e080546316a27d22eba759027f6cb0a24705George Mount        if (getViewsTransition() != null && mTransitioningViews != null) {
22948bd13c9cb2627847cf1f7707a084eb354e9c303George Mount            ViewGroup decorView = getDecor();
23048bd13c9cb2627847cf1f7707a084eb354e9c303George Mount            if (decorView != null) {
23148bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                decorView.captureTransitioningViews(mTransitioningViews);
23248bd13c9cb2627847cf1f7707a084eb354e9c303George Mount            }
23362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            mTransitioningViews.removeAll(mSharedElements);
23431a217290cf376d0573fc36e21c8940987485019George Mount        }
23562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        setEpicenter();
23631a217290cf376d0573fc36e21c8940987485019George Mount    }
23731a217290cf376d0573fc36e21c8940987485019George Mount
238333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount    /**
239333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount     * Iterates over the shared elements and adds them to the members in order.
240333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount     * Shared elements that are nested in other shared elements are placed after the
241333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount     * elements that they are nested in. This means that layout ordering can be done
242333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount     * from first to last.
243333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount     *
244333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount     * @param sharedElements The map of transition names to shared elements to set into
245333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount     *                       the member fields.
246333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount     */
247333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount    private void setSharedElements(ArrayMap<String, View> sharedElements) {
248333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        boolean isFirstRun = true;
249333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        while (!sharedElements.isEmpty()) {
250333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            final int numSharedElements = sharedElements.size();
251333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            for (int i = numSharedElements - 1; i >= 0; i--) {
252333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                final View view = sharedElements.valueAt(i);
253333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                final String name = sharedElements.keyAt(i);
254333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                if (isFirstRun && (view == null || !view.isAttachedToWindow() || name == null)) {
255333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                    sharedElements.removeAt(i);
256333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                } else {
257333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                    if (!isNested(view, sharedElements)) {
258333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                        mSharedElementNames.add(name);
259333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                        mSharedElements.add(view);
260333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                        sharedElements.removeAt(i);
261333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                        if (isFirstRun) {
262333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                            // We need to keep track which shared elements are roots
263333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                            // and which are nested.
264333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                            mRootSharedElements.add(view);
265333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                        }
266333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                    }
267333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                }
268333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            }
269333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            isFirstRun = false;
270333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        }
271333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount    }
272333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount
273333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount    /**
274333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount     * Returns true when view is nested in any of the values of sharedElements.
275333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount     */
276333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount    private static boolean isNested(View view, ArrayMap<String, View> sharedElements) {
277333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        ViewParent parent = view.getParent();
278333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        boolean isNested = false;
279333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        while (parent instanceof View) {
280333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            View parentView = (View) parent;
281333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            if (sharedElements.containsValue(parentView)) {
282333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                isNested = true;
283333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                break;
284333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            }
285333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            parent = parentView.getParent();
286333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        }
287333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        return isNested;
288333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount    }
289333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount
29060625b02ac099bacc96a387ec270751745dafae0George Mount    protected void stripOffscreenViews() {
291b694e080546316a27d22eba759027f6cb0a24705George Mount        if (mTransitioningViews == null) {
292b694e080546316a27d22eba759027f6cb0a24705George Mount            return;
293b694e080546316a27d22eba759027f6cb0a24705George Mount        }
29460625b02ac099bacc96a387ec270751745dafae0George Mount        Rect r = new Rect();
29560625b02ac099bacc96a387ec270751745dafae0George Mount        for (int i = mTransitioningViews.size() - 1; i >= 0; i--) {
29660625b02ac099bacc96a387ec270751745dafae0George Mount            View view = mTransitioningViews.get(i);
29760625b02ac099bacc96a387ec270751745dafae0George Mount            if (!view.getGlobalVisibleRect(r)) {
29860625b02ac099bacc96a387ec270751745dafae0George Mount                mTransitioningViews.remove(i);
299653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount                showView(view, true);
30060625b02ac099bacc96a387ec270751745dafae0George Mount            }
30160625b02ac099bacc96a387ec270751745dafae0George Mount        }
30260625b02ac099bacc96a387ec270751745dafae0George Mount    }
30360625b02ac099bacc96a387ec270751745dafae0George Mount
30431a217290cf376d0573fc36e21c8940987485019George Mount    protected Window getWindow() {
30531a217290cf376d0573fc36e21c8940987485019George Mount        return mWindow;
30631a217290cf376d0573fc36e21c8940987485019George Mount    }
30731a217290cf376d0573fc36e21c8940987485019George Mount
308a2bbbb3bac464c3a52e33008401fed4a7542744cGeorge Mount    public ViewGroup getDecor() {
30931a217290cf376d0573fc36e21c8940987485019George Mount        return (mWindow == null) ? null : (ViewGroup) mWindow.getDecorView();
31031a217290cf376d0573fc36e21c8940987485019George Mount    }
31131a217290cf376d0573fc36e21c8940987485019George Mount
31262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    /**
31362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount     * Sets the transition epicenter to the position of the first shared element.
31462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount     */
31562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected void setEpicenter() {
31662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        View epicenter = null;
317c6186bffe477b996e388046e8761908b813fd07fGeorge Mount        if (!mAllSharedElementNames.isEmpty() && !mSharedElementNames.isEmpty()) {
318c6186bffe477b996e388046e8761908b813fd07fGeorge Mount            int index = mSharedElementNames.indexOf(mAllSharedElementNames.get(0));
319c6186bffe477b996e388046e8761908b813fd07fGeorge Mount            if (index >= 0) {
320c6186bffe477b996e388046e8761908b813fd07fGeorge Mount                epicenter = mSharedElements.get(index);
321c6186bffe477b996e388046e8761908b813fd07fGeorge Mount            }
32231a217290cf376d0573fc36e21c8940987485019George Mount        }
32362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        setEpicenter(epicenter);
32431a217290cf376d0573fc36e21c8940987485019George Mount    }
32531a217290cf376d0573fc36e21c8940987485019George Mount
32662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    private void setEpicenter(View view) {
32762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        if (view == null) {
32862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            mEpicenterCallback.setEpicenter(null);
32931a217290cf376d0573fc36e21c8940987485019George Mount        } else {
3308e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount            Rect epicenter = new Rect();
3318e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount            view.getBoundsOnScreen(epicenter);
33262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            mEpicenterCallback.setEpicenter(epicenter);
33331a217290cf376d0573fc36e21c8940987485019George Mount        }
33431a217290cf376d0573fc36e21c8940987485019George Mount    }
33531a217290cf376d0573fc36e21c8940987485019George Mount
33662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public ArrayList<String> getAcceptedNames() {
33762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        return mSharedElementNames;
33831a217290cf376d0573fc36e21c8940987485019George Mount    }
33931a217290cf376d0573fc36e21c8940987485019George Mount
34062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public ArrayList<String> getMappedNames() {
34162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        ArrayList<String> names = new ArrayList<String>(mSharedElements.size());
34262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        for (int i = 0; i < mSharedElements.size(); i++) {
3430a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount            names.add(mSharedElements.get(i).getTransitionName());
344080443bcb63418245c2408500db735fece5e7083George Mount        }
34562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        return names;
34631a217290cf376d0573fc36e21c8940987485019George Mount    }
34731a217290cf376d0573fc36e21c8940987485019George Mount
348700db2a325bced35cebc403f272f988fad522892George Mount    public ArrayList<View> copyMappedViews() {
349700db2a325bced35cebc403f272f988fad522892George Mount        return new ArrayList<View>(mSharedElements);
3501fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount    }
3511fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount
3528c2614ce4328640642d8e8be437859e0508a39b4George Mount    public ArrayList<String> getAllSharedElementNames() { return mAllSharedElementNames; }
3538c2614ce4328640642d8e8be437859e0508a39b4George Mount
3548881502da5b319e139ab85c1825d2d2d239356a1George Mount    protected Transition setTargets(Transition transition, boolean add) {
3558881502da5b319e139ab85c1825d2d2d239356a1George Mount        if (transition == null || (add &&
3568881502da5b319e139ab85c1825d2d2d239356a1George Mount                (mTransitioningViews == null || mTransitioningViews.isEmpty()))) {
35731a217290cf376d0573fc36e21c8940987485019George Mount            return null;
35831a217290cf376d0573fc36e21c8940987485019George Mount        }
359d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        // Add the targets to a set containing transition so that transition
360d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        // remains unaffected. We don't want to modify the targets of transition itself.
36131a217290cf376d0573fc36e21c8940987485019George Mount        TransitionSet set = new TransitionSet();
3628881502da5b319e139ab85c1825d2d2d239356a1George Mount        if (mTransitioningViews != null) {
3638881502da5b319e139ab85c1825d2d2d239356a1George Mount            for (int i = mTransitioningViews.size() - 1; i >= 0; i--) {
3648881502da5b319e139ab85c1825d2d2d239356a1George Mount                View view = mTransitioningViews.get(i);
3658881502da5b319e139ab85c1825d2d2d239356a1George Mount                if (add) {
3668881502da5b319e139ab85c1825d2d2d239356a1George Mount                    set.addTarget(view);
3678881502da5b319e139ab85c1825d2d2d239356a1George Mount                } else {
3688881502da5b319e139ab85c1825d2d2d239356a1George Mount                    set.excludeTarget(view, true);
3698881502da5b319e139ab85c1825d2d2d239356a1George Mount                }
37031a217290cf376d0573fc36e21c8940987485019George Mount            }
37131a217290cf376d0573fc36e21c8940987485019George Mount        }
372d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        // By adding the transition after addTarget, we prevent addTarget from
373d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        // affecting transition.
374d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount        set.addTransition(transition);
375fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
376fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        if (!add && mTransitioningViews != null && !mTransitioningViews.isEmpty()) {
377fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            // Allow children of excluded transitioning views, but not the views themselves
378fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            set = new TransitionSet().addTransition(set);
379fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        }
380fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
38131a217290cf376d0573fc36e21c8940987485019George Mount        return set;
38231a217290cf376d0573fc36e21c8940987485019George Mount    }
38331a217290cf376d0573fc36e21c8940987485019George Mount
3848881502da5b319e139ab85c1825d2d2d239356a1George Mount    protected Transition configureTransition(Transition transition,
3858881502da5b319e139ab85c1825d2d2d239356a1George Mount            boolean includeTransitioningViews) {
38631a217290cf376d0573fc36e21c8940987485019George Mount        if (transition != null) {
38762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            transition = transition.clone();
38862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            transition.setEpicenterCallback(mEpicenterCallback);
3898881502da5b319e139ab85c1825d2d2d239356a1George Mount            transition = setTargets(transition, includeTransitioningViews);
39031a217290cf376d0573fc36e21c8940987485019George Mount        }
39131a217290cf376d0573fc36e21c8940987485019George Mount        return transition;
39231a217290cf376d0573fc36e21c8940987485019George Mount    }
39331a217290cf376d0573fc36e21c8940987485019George Mount
39462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static Transition mergeTransitions(Transition transition1, Transition transition2) {
39562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        if (transition1 == null) {
39662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            return transition2;
39762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        } else if (transition2 == null) {
39862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            return transition1;
39962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        } else {
40062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            TransitionSet transitionSet = new TransitionSet();
40162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            transitionSet.addTransition(transition1);
40262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            transitionSet.addTransition(transition2);
40362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            return transitionSet;
40462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        }
40562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    }
40662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount
4071fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount    protected ArrayMap<String, View> mapSharedElements(ArrayList<String> accepted,
4081fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount            ArrayList<View> localViews) {
4091fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount        ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
410ce725a47f6eee75a6ef86397e9b9fe471aeb1f84George Mount        if (accepted != null) {
411ce725a47f6eee75a6ef86397e9b9fe471aeb1f84George Mount            for (int i = 0; i < accepted.size(); i++) {
412ce725a47f6eee75a6ef86397e9b9fe471aeb1f84George Mount                sharedElements.put(accepted.get(i), localViews.get(i));
413caa03107d4322b0e30f92e6dc1eb1ea73b1bf747George Mount            }
414ce725a47f6eee75a6ef86397e9b9fe471aeb1f84George Mount        } else {
41548bd13c9cb2627847cf1f7707a084eb354e9c303George Mount            ViewGroup decorView = getDecor();
41648bd13c9cb2627847cf1f7707a084eb354e9c303George Mount            if (decorView != null) {
41748bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                decorView.findNamedViews(sharedElements);
41848bd13c9cb2627847cf1f7707a084eb354e9c303George Mount            }
4191fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount        }
4201fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount        return sharedElements;
4211fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount    }
4221fecfb2ddcdf4335ff543bdd549b8e4d36139da8George Mount
42362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected void setResultReceiver(ResultReceiver resultReceiver) {
42462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        mResultReceiver = resultReceiver;
425080443bcb63418245c2408500db735fece5e7083George Mount    }
426080443bcb63418245c2408500db735fece5e7083George Mount
427a712e8cc2f16ac32ee5f1bbf5b962969f2f3451eGeorge Mount    protected abstract Transition getViewsTransition();
428080443bcb63418245c2408500db735fece5e7083George Mount
429fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    private void setSharedElementState(View view, String name, Bundle transitionArgs,
4307bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            Matrix tempMatrix, RectF tempRect, int[] decorLoc) {
431c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        Bundle sharedElementBundle = transitionArgs.getBundle(name);
432c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (sharedElementBundle == null) {
433c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            return;
434c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
435c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
436c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (view instanceof ImageView) {
437c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            int scaleTypeInt = sharedElementBundle.getInt(KEY_SCALE_TYPE, -1);
438c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            if (scaleTypeInt >= 0) {
439c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                ImageView imageView = (ImageView) view;
440c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                ImageView.ScaleType scaleType = SCALE_TYPE_VALUES[scaleTypeInt];
441c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                imageView.setScaleType(scaleType);
442c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                if (scaleType == ImageView.ScaleType.MATRIX) {
443c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                    float[] matrixValues = sharedElementBundle.getFloatArray(KEY_IMAGE_MATRIX);
4447bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu                    tempMatrix.setValues(matrixValues);
4457bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu                    imageView.setImageMatrix(tempMatrix);
446c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                }
447c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            }
448c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
449c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
450c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
451c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        view.setTranslationZ(z);
45226c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount        float elevation = sharedElementBundle.getFloat(KEY_ELEVATION);
45326c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount        view.setElevation(elevation);
454c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
4557bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        float left = sharedElementBundle.getFloat(KEY_SCREEN_LEFT);
4567bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        float top = sharedElementBundle.getFloat(KEY_SCREEN_TOP);
4577bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        float right = sharedElementBundle.getFloat(KEY_SCREEN_RIGHT);
4587bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        float bottom = sharedElementBundle.getFloat(KEY_SCREEN_BOTTOM);
459c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
4607bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        if (decorLoc != null) {
4617bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            left -= decorLoc[0];
4627bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            top -= decorLoc[1];
463480ca829e2d3313740b4d14d30afbea6c98ff965George Mount            right -= decorLoc[0];
464480ca829e2d3313740b4d14d30afbea6c98ff965George Mount            bottom -= decorLoc[1];
4657bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        } else {
4667bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            // Find the location in the view's parent
467fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            getSharedElementParentMatrix(view, tempMatrix);
4687bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            tempRect.set(left, top, right, bottom);
4697bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            tempMatrix.mapRect(tempRect);
4707bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu
4717bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            float leftInParent = tempRect.left;
4727bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            float topInParent = tempRect.top;
4737bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu
4747bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            // Find the size of the view
4757bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            view.getInverseMatrix().mapRect(tempRect);
4767bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            float width = tempRect.width();
4777bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            float height = tempRect.height();
4787bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu
4797bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            // Now determine the offset due to view transform:
4807bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            view.setLeft(0);
4817bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            view.setTop(0);
4827bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            view.setRight(Math.round(width));
4837bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            view.setBottom(Math.round(height));
4847bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            tempRect.set(0, 0, width, height);
4857bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            view.getMatrix().mapRect(tempRect);
4867bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu
487fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            ViewGroup parent = (ViewGroup) view.getParent();
4887bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            left = leftInParent - tempRect.left + parent.getScrollX();
4897bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            top = topInParent - tempRect.top + parent.getScrollY();
4907bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            right = left + width;
4917bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            bottom = top + height;
4927bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        }
4937bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu
4947bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        int x = Math.round(left);
4957bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        int y = Math.round(top);
4967bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        int width = Math.round(right) - x;
4977bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        int height = Math.round(bottom) - y;
498c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
499c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
500c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        view.measure(widthSpec, heightSpec);
501c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
5027bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        view.layout(x, y, x + width, y + height);
503c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
504c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
505333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount    private void setSharedElementMatrices() {
506333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        int numSharedElements = mSharedElements.size();
507333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        if (numSharedElements > 0) {
508333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            mSharedElementParentMatrices = new ArrayList<Matrix>(numSharedElements);
509333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        }
510333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        for (int i = 0; i < numSharedElements; i++) {
511333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            View view = mSharedElements.get(i);
512333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount
513333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            // Find the location in the view's parent
514333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            ViewGroup parent = (ViewGroup) view.getParent();
515333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            Matrix matrix = new Matrix();
516333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            parent.transformMatrixToLocal(matrix);
517333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount
518333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            mSharedElementParentMatrices.add(matrix);
519333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        }
520333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount    }
521333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount
522333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount    private void getSharedElementParentMatrix(View view, Matrix matrix) {
523333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        final boolean isNestedInOtherSharedElement = !mRootSharedElements.contains(view);
524333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        final boolean useParentMatrix;
525333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        if (isNestedInOtherSharedElement) {
526333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            useParentMatrix = true;
527333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        } else {
528333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            final int index = mSharedElementParentMatrices == null ? -1
529333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                    : mSharedElements.indexOf(view);
530333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            if (index < 0) {
531333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                useParentMatrix = true;
532333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            } else {
533333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                // The indices of mSharedElementParentMatrices matches the
534333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                // mSharedElement matrices.
535333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                Matrix parentMatrix = mSharedElementParentMatrices.get(index);
536333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                matrix.set(parentMatrix);
537333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                useParentMatrix = false;
538333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            }
539333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        }
540333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        if (useParentMatrix) {
541333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            matrix.reset();
542333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            ViewParent viewParent = view.getParent();
543333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            if (viewParent instanceof ViewGroup) {
544333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                // Find the location in the view's parent
545333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                ViewGroup parent = (ViewGroup) viewParent;
546333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount                parent.transformMatrixToLocal(matrix);
547333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount            }
548333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        }
549fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    }
550fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
551c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu    protected ArrayList<SharedElementOriginalState> setSharedElementState(
552c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            Bundle sharedElementState, final ArrayList<View> snapshots) {
553c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        ArrayList<SharedElementOriginalState> originalImageState =
554c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu                new ArrayList<SharedElementOriginalState>();
555c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (sharedElementState != null) {
5567bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            Matrix tempMatrix = new Matrix();
5577bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            RectF tempRect = new RectF();
5581732f528952ea2df0bfd503fabb958af03dbfc81George Mount            final int numSharedElements = mSharedElements.size();
5591732f528952ea2df0bfd503fabb958af03dbfc81George Mount            for (int i = 0; i < numSharedElements; i++) {
560c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                View sharedElement = mSharedElements.get(i);
561c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                String name = mSharedElementNames.get(i);
562c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu                SharedElementOriginalState originalState = getOldSharedElementState(sharedElement,
563c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                        name, sharedElementState);
564c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu                originalImageState.add(originalState);
5657bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu                setSharedElementState(sharedElement, name, sharedElementState,
5667bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu                        tempMatrix, tempRect, null);
567c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            }
568c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
5691732f528952ea2df0bfd503fabb958af03dbfc81George Mount        if (mListener != null) {
5701732f528952ea2df0bfd503fabb958af03dbfc81George Mount            mListener.onSharedElementStart(mSharedElementNames, mSharedElements, snapshots);
5711732f528952ea2df0bfd503fabb958af03dbfc81George Mount        }
572fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        return originalImageState;
573fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    }
574fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
575fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    protected void notifySharedElementEnd(ArrayList<View> snapshots) {
5761732f528952ea2df0bfd503fabb958af03dbfc81George Mount        if (mListener != null) {
5771732f528952ea2df0bfd503fabb958af03dbfc81George Mount            mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, snapshots);
5781732f528952ea2df0bfd503fabb958af03dbfc81George Mount        }
579fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    }
580c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
581fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    protected void scheduleSetSharedElementEnd(final ArrayList<View> snapshots) {
5826e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount        final View decorView = getDecor();
58348bd13c9cb2627847cf1f7707a084eb354e9c303George Mount        if (decorView != null) {
58448bd13c9cb2627847cf1f7707a084eb354e9c303George Mount            decorView.getViewTreeObserver().addOnPreDrawListener(
58548bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                    new ViewTreeObserver.OnPreDrawListener() {
58648bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                        @Override
58748bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                        public boolean onPreDraw() {
58848bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                            decorView.getViewTreeObserver().removeOnPreDrawListener(this);
58948bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                            notifySharedElementEnd(snapshots);
59048bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                            return true;
59148bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                        }
592c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                    }
59348bd13c9cb2627847cf1f7707a084eb354e9c303George Mount            );
59448bd13c9cb2627847cf1f7707a084eb354e9c303George Mount        }
595c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
596c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
597c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu    private static SharedElementOriginalState getOldSharedElementState(View view, String name,
598c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            Bundle transitionArgs) {
599c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu
600c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        SharedElementOriginalState state = new SharedElementOriginalState();
601c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        state.mLeft = view.getLeft();
602c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        state.mTop = view.getTop();
603c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        state.mRight = view.getRight();
604c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        state.mBottom = view.getBottom();
605c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        state.mMeasuredWidth = view.getMeasuredWidth();
606c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        state.mMeasuredHeight = view.getMeasuredHeight();
60726c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount        state.mTranslationZ = view.getTranslationZ();
60826c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount        state.mElevation = view.getElevation();
609c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (!(view instanceof ImageView)) {
610c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            return state;
611c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
612c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        Bundle bundle = transitionArgs.getBundle(name);
613c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (bundle == null) {
614c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            return state;
615c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
616c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int scaleTypeInt = bundle.getInt(KEY_SCALE_TYPE, -1);
617c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (scaleTypeInt < 0) {
618c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            return state;
619c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
620c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
621c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        ImageView imageView = (ImageView) view;
622c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        state.mScaleType = imageView.getScaleType();
623c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        if (state.mScaleType == ImageView.ScaleType.MATRIX) {
624c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            state.mMatrix = new Matrix(imageView.getImageMatrix());
625c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
626c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        return state;
627c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
628c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
629c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    protected ArrayList<View> createSnapshots(Bundle state, Collection<String> names) {
630c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int numSharedElements = names.size();
6317c479f5a013fb5544be45cd3a952190fc3a923fcGeorge Mount        ArrayList<View> snapshots = new ArrayList<View>(numSharedElements);
632c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (numSharedElements == 0) {
6337c479f5a013fb5544be45cd3a952190fc3a923fcGeorge Mount            return snapshots;
634c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
635c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        Context context = getWindow().getContext();
6367bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        int[] decorLoc = new int[2];
63748bd13c9cb2627847cf1f7707a084eb354e9c303George Mount        ViewGroup decorView = getDecor();
63848bd13c9cb2627847cf1f7707a084eb354e9c303George Mount        if (decorView != null) {
63948bd13c9cb2627847cf1f7707a084eb354e9c303George Mount            decorView.getLocationOnScreen(decorLoc);
64048bd13c9cb2627847cf1f7707a084eb354e9c303George Mount        }
641ca5094a05ce177c586f873ad556e7afc2656fe12George Mount        Matrix tempMatrix = new Matrix();
642c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        for (String name: names) {
643c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            Bundle sharedElementBundle = state.getBundle(name);
64492692c0284c2249e9a5381f7f19ec97f6b76d12fGeorge Mount            View snapshot = null;
645c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            if (sharedElementBundle != null) {
646480ca829e2d3313740b4d14d30afbea6c98ff965George Mount                Parcelable parcelable = sharedElementBundle.getParcelable(KEY_SNAPSHOT);
6471732f528952ea2df0bfd503fabb958af03dbfc81George Mount                if (parcelable != null && mListener != null) {
6486558056e8fccc32f9e1dc59e46d09f8d916b7538George Mount                    snapshot = mListener.onCreateSnapshotView(context, parcelable);
649480ca829e2d3313740b4d14d30afbea6c98ff965George Mount                }
650480ca829e2d3313740b4d14d30afbea6c98ff965George Mount                if (snapshot != null) {
651ca5094a05ce177c586f873ad556e7afc2656fe12George Mount                    setSharedElementState(snapshot, name, state, tempMatrix, null, decorLoc);
652c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                }
653c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            }
65492692c0284c2249e9a5381f7f19ec97f6b76d12fGeorge Mount            // Even null snapshots are added so they remain in the same order as shared elements.
65592692c0284c2249e9a5381f7f19ec97f6b76d12fGeorge Mount            snapshots.add(snapshot);
656c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
657c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        return snapshots;
658c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
659c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
660c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu    protected static void setOriginalSharedElementState(ArrayList<View> sharedElements,
661c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            ArrayList<SharedElementOriginalState> originalState) {
662c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        for (int i = 0; i < originalState.size(); i++) {
663c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            View view = sharedElements.get(i);
664c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            SharedElementOriginalState state = originalState.get(i);
665c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            if (view instanceof ImageView && state.mScaleType != null) {
666c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu                ImageView imageView = (ImageView) view;
667c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu                imageView.setScaleType(state.mScaleType);
668c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu                if (state.mScaleType == ImageView.ScaleType.MATRIX) {
669c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu                  imageView.setImageMatrix(state.mMatrix);
670c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu                }
671c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            }
67226c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount            view.setElevation(state.mElevation);
67326c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount            view.setTranslationZ(state.mTranslationZ);
67426c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount            int widthSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredWidth,
675c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu                    View.MeasureSpec.EXACTLY);
676c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            int heightSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredHeight,
677c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu                    View.MeasureSpec.EXACTLY);
678c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            view.measure(widthSpec, heightSpec);
679c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu            view.layout(state.mLeft, state.mTop, state.mRight, state.mBottom);
680c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
681c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
682c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
683c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    protected Bundle captureSharedElementState() {
684c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        Bundle bundle = new Bundle();
6857bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        RectF tempBounds = new RectF();
6867bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        Matrix tempMatrix = new Matrix();
687f03c139018dd5b6f1ea53ac902caec7b6ee9ddd3Dake Gu        for (int i = 0; i < mSharedElements.size(); i++) {
688c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            View sharedElement = mSharedElements.get(i);
689c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            String name = mSharedElementNames.get(i);
6907bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            captureSharedElementState(sharedElement, name, bundle, tempMatrix, tempBounds);
691c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
692c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        return bundle;
693c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
694c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
695a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount    protected void clearState() {
696a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount        // Clear the state so that we can't hold any references accidentally and leak memory.
697a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount        mWindow = null;
698a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount        mSharedElements.clear();
699b694e080546316a27d22eba759027f6cb0a24705George Mount        mTransitioningViews = null;
7000f0c473488f8e8becc8883d3cdd9610324610dc4George Mount        mOriginalAlphas.clear();
701a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount        mResultReceiver = null;
702a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount        mPendingTransition = null;
703fc0fc0e341f2a2d707d5a8eafd65db34bdffb35cDake Gu        mListener = null;
704333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        mRootSharedElements.clear();
705333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        mSharedElementParentMatrices = null;
706a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount    }
707a0a0260e48e1ee4e9b5d98b49571e8d2a6fd6c3aGeorge Mount
708ed1e01d7e431edbcaab983b4b240418f2b090facGeorge Mount    protected long getFadeDuration() {
709ed1e01d7e431edbcaab983b4b240418f2b090facGeorge Mount        return getWindow().getTransitionBackgroundFadeDuration();
710ed1e01d7e431edbcaab983b4b240418f2b090facGeorge Mount    }
711ed1e01d7e431edbcaab983b4b240418f2b090facGeorge Mount
7120f0c473488f8e8becc8883d3cdd9610324610dc4George Mount    protected void hideViews(ArrayList<View> views) {
713fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        int count = views.size();
714fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        for (int i = 0; i < count; i++) {
7150f0c473488f8e8becc8883d3cdd9610324610dc4George Mount            View view = views.get(i);
7160f0c473488f8e8becc8883d3cdd9610324610dc4George Mount            if (!mOriginalAlphas.containsKey(view)) {
7170f0c473488f8e8becc8883d3cdd9610324610dc4George Mount                mOriginalAlphas.put(view, view.getAlpha());
7180f0c473488f8e8becc8883d3cdd9610324610dc4George Mount            }
7190f0c473488f8e8becc8883d3cdd9610324610dc4George Mount            view.setAlpha(0f);
7200f0c473488f8e8becc8883d3cdd9610324610dc4George Mount        }
7210f0c473488f8e8becc8883d3cdd9610324610dc4George Mount    }
7220f0c473488f8e8becc8883d3cdd9610324610dc4George Mount
723ce2ee3d6de670e52abed7f432778701113ba9c07George Mount    protected void showViews(ArrayList<View> views, boolean setTransitionAlpha) {
7240f0c473488f8e8becc8883d3cdd9610324610dc4George Mount        int count = views.size();
7250f0c473488f8e8becc8883d3cdd9610324610dc4George Mount        for (int i = 0; i < count; i++) {
726653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount            showView(views.get(i), setTransitionAlpha);
727653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount        }
728653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount    }
729653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount
730653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount    private void showView(View view, boolean setTransitionAlpha) {
731653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount        Float alpha = mOriginalAlphas.remove(view);
732653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount        if (alpha != null) {
733653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount            view.setAlpha(alpha);
734653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount        }
735653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount        if (setTransitionAlpha) {
736653ea66a9f609deec4b4370550396c47a85d713cGeorge Mount            view.setTransitionAlpha(1f);
737b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        }
738b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    }
739b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount
740c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    /**
741c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * Captures placement information for Views with a shared element name for
742c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * Activity Transitions.
743c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     *
744c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * @param view           The View to capture the placement information for.
745c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * @param name           The shared element name in the target Activity to apply the placement
746c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     *                       information for.
747c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * @param transitionArgs Bundle to store shared element placement information.
7488e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount     * @param tempBounds     A temporary Rect for capturing the current location of views.
749c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     */
750480ca829e2d3313740b4d14d30afbea6c98ff965George Mount    protected void captureSharedElementState(View view, String name, Bundle transitionArgs,
7517bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu            Matrix tempMatrix, RectF tempBounds) {
752c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        Bundle sharedElementBundle = new Bundle();
7537bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        tempMatrix.reset();
7547bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        view.transformMatrixToGlobal(tempMatrix);
7558e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount        tempBounds.set(0, 0, view.getWidth(), view.getHeight());
7567bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        tempMatrix.mapRect(tempBounds);
757c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
7587bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        sharedElementBundle.putFloat(KEY_SCREEN_LEFT, tempBounds.left);
7597bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        sharedElementBundle.putFloat(KEY_SCREEN_RIGHT, tempBounds.right);
7607bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        sharedElementBundle.putFloat(KEY_SCREEN_TOP, tempBounds.top);
7617bf379c8af399626d5b8b568fe1d4f96f56badccDake Gu        sharedElementBundle.putFloat(KEY_SCREEN_BOTTOM, tempBounds.bottom);
762c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ());
76326c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount        sharedElementBundle.putFloat(KEY_ELEVATION, view.getElevation());
764c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
7651732f528952ea2df0bfd503fabb958af03dbfc81George Mount        Parcelable bitmap = null;
7661732f528952ea2df0bfd503fabb958af03dbfc81George Mount        if (mListener != null) {
7671732f528952ea2df0bfd503fabb958af03dbfc81George Mount            bitmap = mListener.onCaptureSharedElementSnapshot(view, tempMatrix, tempBounds);
7681732f528952ea2df0bfd503fabb958af03dbfc81George Mount        }
7691732f528952ea2df0bfd503fabb958af03dbfc81George Mount
770480ca829e2d3313740b4d14d30afbea6c98ff965George Mount        if (bitmap != null) {
771480ca829e2d3313740b4d14d30afbea6c98ff965George Mount            sharedElementBundle.putParcelable(KEY_SNAPSHOT, bitmap);
772c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
773c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
774c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (view instanceof ImageView) {
775c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            ImageView imageView = (ImageView) view;
776c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            int scaleTypeInt = scaleTypeToInt(imageView.getScaleType());
777c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            sharedElementBundle.putInt(KEY_SCALE_TYPE, scaleTypeInt);
778c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            if (imageView.getScaleType() == ImageView.ScaleType.MATRIX) {
779c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                float[] matrix = new float[9];
780c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                imageView.getImageMatrix().getValues(matrix);
781c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                sharedElementBundle.putFloatArray(KEY_IMAGE_MATRIX, matrix);
782c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            }
783c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
784c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
785c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        transitionArgs.putBundle(name, sharedElementBundle);
786c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
787c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
78867d924341a1d0994ac68b3b7898d5576edd987b4George Mount
78967d924341a1d0994ac68b3b7898d5576edd987b4George Mount    protected void startTransition(Runnable runnable) {
79067d924341a1d0994ac68b3b7898d5576edd987b4George Mount        if (mIsStartingTransition) {
79167d924341a1d0994ac68b3b7898d5576edd987b4George Mount            mPendingTransition = runnable;
79267d924341a1d0994ac68b3b7898d5576edd987b4George Mount        } else {
79367d924341a1d0994ac68b3b7898d5576edd987b4George Mount            mIsStartingTransition = true;
79467d924341a1d0994ac68b3b7898d5576edd987b4George Mount            runnable.run();
79567d924341a1d0994ac68b3b7898d5576edd987b4George Mount        }
79667d924341a1d0994ac68b3b7898d5576edd987b4George Mount    }
79767d924341a1d0994ac68b3b7898d5576edd987b4George Mount
79813ccb79b34f6db1580714ea980c8490121d7e5aeGeorge Mount    protected void transitionStarted() {
79913ccb79b34f6db1580714ea980c8490121d7e5aeGeorge Mount        mIsStartingTransition = false;
80013ccb79b34f6db1580714ea980c8490121d7e5aeGeorge Mount    }
80113ccb79b34f6db1580714ea980c8490121d7e5aeGeorge Mount
802fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount    /**
803fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount     * Cancels any pending transitions and returns true if there is a transition is in
804fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount     * the middle of starting.
805fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount     */
806fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount    protected boolean cancelPendingTransitions() {
807fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount        mPendingTransition = null;
808fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount        return mIsStartingTransition;
809fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount    }
810fbd459642fe732115f135e456eafdec2dc8e9bb6George Mount
811fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    protected void moveSharedElementsToOverlay() {
812eca1ae5e442bf5f13617ab823343730619512632George Mount        if (mWindow == null || !mWindow.getSharedElementsUseOverlay()) {
813b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount            return;
814b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount        }
815333b8093eaab4b55d91a7a0b3b1484424f8ac975George Mount        setSharedElementMatrices();
816fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        int numSharedElements = mSharedElements.size();
817fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        ViewGroup decor = getDecor();
818fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        if (decor != null) {
819fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            boolean moveWithParent = moveSharedElementWithParent();
820fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            for (int i = 0; i < numSharedElements; i++) {
821fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                View view = mSharedElements.get(i);
822fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                GhostView.addGhost(view, decor);
823fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                ViewGroup parent = (ViewGroup) view.getParent();
824fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                if (moveWithParent && !isInTransitionGroup(parent, decor)) {
8256e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount                    GhostViewListeners listener = new GhostViewListeners(view, parent, decor);
826fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                    parent.getViewTreeObserver().addOnPreDrawListener(listener);
827fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                    mGhostViewListeners.add(listener);
828fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                }
829fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            }
830fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        }
831fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    }
832fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
833fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    protected boolean moveSharedElementWithParent() {
834fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        return true;
835fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    }
836fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
837fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    public static boolean isInTransitionGroup(ViewParent viewParent, ViewGroup decor) {
838fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        if (viewParent == decor || !(viewParent instanceof ViewGroup)) {
839fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            return false;
840fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        }
841fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        ViewGroup parent = (ViewGroup) viewParent;
842fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        if (parent.isTransitionGroup()) {
843fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            return true;
844fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        } else {
845fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            return isInTransitionGroup(parent.getParent(), decor);
846fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        }
847fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    }
848fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
849fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    protected void moveSharedElementsFromOverlay() {
850b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount        int numListeners = mGhostViewListeners.size();
851b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount        for (int i = 0; i < numListeners; i++) {
852b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount            GhostViewListeners listener = mGhostViewListeners.get(i);
853b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount            ViewGroup parent = (ViewGroup) listener.getView().getParent();
854b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount            parent.getViewTreeObserver().removeOnPreDrawListener(listener);
855b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount        }
856b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount        mGhostViewListeners.clear();
857b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount
858b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount        if (mWindow == null || !mWindow.getSharedElementsUseOverlay()) {
859b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount            return;
860b89d5cc2c64112a0ff7e66e4dd3bb2114caed935George Mount        }
861fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        ViewGroup decor = getDecor();
862fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        if (decor != null) {
863fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            ViewGroupOverlay overlay = decor.getOverlay();
864fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            int count = mSharedElements.size();
865fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            for (int i = 0; i < count; i++) {
866fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                View sharedElement = mSharedElements.get(i);
867fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                GhostView.removeGhost(sharedElement);
868fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            }
869fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        }
870fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    }
871fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
872fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    protected void setGhostVisibility(int visibility) {
873fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        int numSharedElements = mSharedElements.size();
874fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        for (int i = 0; i < numSharedElements; i++) {
875fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            GhostView ghostView = GhostView.getGhost(mSharedElements.get(i));
876fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            if (ghostView != null) {
877fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                ghostView.setVisibility(visibility);
878fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            }
879fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        }
880fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    }
881fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
882fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    protected void scheduleGhostVisibilityChange(final int visibility) {
8836e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount        final View decorView = getDecor();
88448bd13c9cb2627847cf1f7707a084eb354e9c303George Mount        if (decorView != null) {
88548bd13c9cb2627847cf1f7707a084eb354e9c303George Mount            decorView.getViewTreeObserver()
88648bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                    .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
88748bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                        @Override
88848bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                        public boolean onPreDraw() {
88948bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                            decorView.getViewTreeObserver().removeOnPreDrawListener(this);
89048bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                            setGhostVisibility(visibility);
89148bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                            return true;
89248bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                        }
89348bd13c9cb2627847cf1f7707a084eb354e9c303George Mount                    });
89448bd13c9cb2627847cf1f7707a084eb354e9c303George Mount        }
895fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    }
896fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
89767d924341a1d0994ac68b3b7898d5576edd987b4George Mount    protected class ContinueTransitionListener extends Transition.TransitionListenerAdapter {
89867d924341a1d0994ac68b3b7898d5576edd987b4George Mount        @Override
89967d924341a1d0994ac68b3b7898d5576edd987b4George Mount        public void onTransitionStart(Transition transition) {
90067d924341a1d0994ac68b3b7898d5576edd987b4George Mount            mIsStartingTransition = false;
90167d924341a1d0994ac68b3b7898d5576edd987b4George Mount            Runnable pending = mPendingTransition;
90267d924341a1d0994ac68b3b7898d5576edd987b4George Mount            mPendingTransition = null;
90367d924341a1d0994ac68b3b7898d5576edd987b4George Mount            if (pending != null) {
90467d924341a1d0994ac68b3b7898d5576edd987b4George Mount                startTransition(pending);
90567d924341a1d0994ac68b3b7898d5576edd987b4George Mount            }
90667d924341a1d0994ac68b3b7898d5576edd987b4George Mount        }
90767d924341a1d0994ac68b3b7898d5576edd987b4George Mount    }
90867d924341a1d0994ac68b3b7898d5576edd987b4George Mount
909c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    private static int scaleTypeToInt(ImageView.ScaleType scaleType) {
910c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        for (int i = 0; i < SCALE_TYPE_VALUES.length; i++) {
911c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            if (scaleType == SCALE_TYPE_VALUES[i]) {
912c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                return i;
913c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            }
914c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
915c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        return -1;
916c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
917c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
91831a217290cf376d0573fc36e21c8940987485019George Mount    private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
91931a217290cf376d0573fc36e21c8940987485019George Mount        private Rect mEpicenter;
92031a217290cf376d0573fc36e21c8940987485019George Mount
92131a217290cf376d0573fc36e21c8940987485019George Mount        public void setEpicenter(Rect epicenter) { mEpicenter = epicenter; }
92231a217290cf376d0573fc36e21c8940987485019George Mount
92331a217290cf376d0573fc36e21c8940987485019George Mount        @Override
924dc21d3b2804c24fe29ec860796d11185901364c4George Mount        public Rect onGetEpicenter(Transition transition) {
92531a217290cf376d0573fc36e21c8940987485019George Mount            return mEpicenter;
92631a217290cf376d0573fc36e21c8940987485019George Mount        }
92731a217290cf376d0573fc36e21c8940987485019George Mount    }
928800d72b0e05049e4a8f90ea96ec165fc975264ceGeorge Mount
929fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    private static class GhostViewListeners implements ViewTreeObserver.OnPreDrawListener {
930fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        private View mView;
931fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        private ViewGroup mDecor;
9326e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount        private View mParent;
933fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        private Matrix mMatrix = new Matrix();
934fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
9356e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount        public GhostViewListeners(View view, View parent, ViewGroup decor) {
936fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            mView = view;
9376e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount            mParent = parent;
938fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            mDecor = decor;
939fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        }
940fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
941fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        public View getView() {
942fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            return mView;
943fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        }
944fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
945fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        @Override
946fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        public boolean onPreDraw() {
947fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            GhostView ghostView = GhostView.getGhost(mView);
948fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            if (ghostView == null) {
9496e7fb60b93d3449d256282a9cc34ba3356add90eGeorge Mount                mParent.getViewTreeObserver().removeOnPreDrawListener(this);
950fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            } else {
951fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                GhostView.calculateMatrix(mView, mDecor, mMatrix);
952fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount                ghostView.setMatrix(mMatrix);
953fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            }
954fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount            return true;
955fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount        }
956fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount    }
957fe361d2113b8f3c54797d7bd720ca739328bd7aaGeorge Mount
958c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu    static class SharedElementOriginalState {
959c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        int mLeft;
960c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        int mTop;
961c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        int mRight;
962c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        int mBottom;
963c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        int mMeasuredWidth;
964c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        int mMeasuredHeight;
965c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        ImageView.ScaleType mScaleType;
966c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu        Matrix mMatrix;
96726c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount        float mTranslationZ;
96826c82b6ed1e8e7276fe2ca65c241fc4c4cac6d12George Mount        float mElevation;
969c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5Dake Gu    }
97031a217290cf376d0573fc36e21c8940987485019George Mount}
971