ActivityTransitionCoordinator.java revision 8c2614ce4328640642d8e8be437859e0508a39b4
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.content.res.Resources;
20c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mountimport android.graphics.Bitmap;
21c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mountimport android.graphics.Canvas;
22c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mountimport android.graphics.Matrix;
2331a217290cf376d0573fc36e21c8940987485019George Mountimport android.graphics.Rect;
24c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mountimport android.graphics.drawable.BitmapDrawable;
25c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mountimport android.os.Bundle;
2631a217290cf376d0573fc36e21c8940987485019George Mountimport android.os.Handler;
2731a217290cf376d0573fc36e21c8940987485019George Mountimport android.os.ResultReceiver;
2831a217290cf376d0573fc36e21c8940987485019George Mountimport android.transition.Transition;
2931a217290cf376d0573fc36e21c8940987485019George Mountimport android.transition.TransitionSet;
3031a217290cf376d0573fc36e21c8940987485019George Mountimport android.util.ArrayMap;
31c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mountimport android.util.Pair;
3231a217290cf376d0573fc36e21c8940987485019George Mountimport android.view.View;
3331a217290cf376d0573fc36e21c8940987485019George Mountimport android.view.ViewGroup;
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
12362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static final String KEY_SCREEN_X = "shared_element:screenX";
12462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static final String KEY_SCREEN_Y = "shared_element:screenY";
12562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static final String KEY_TRANSLATION_Z = "shared_element:translationZ";
12662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static final String KEY_WIDTH = "shared_element:width";
12762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static final String KEY_HEIGHT = "shared_element:height";
12862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static final String KEY_BITMAP = "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";
13131a217290cf376d0573fc36e21c8940987485019George Mount
132d265bd7446e662c9597226c596e8f91eda824982George Mount    // The background fade in/out duration. TODO: Enable tuning this.
133d265bd7446e662c9597226c596e8f91eda824982George Mount    public static final int FADE_BACKGROUND_DURATION_MS = 300;
134080443bcb63418245c2408500db735fece5e7083George Mount
13562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static final ImageView.ScaleType[] SCALE_TYPE_VALUES = ImageView.ScaleType.values();
13631a217290cf376d0573fc36e21c8940987485019George Mount
13731a217290cf376d0573fc36e21c8940987485019George Mount    /**
13831a217290cf376d0573fc36e21c8940987485019George Mount     * Sent by the exiting coordinator (either EnterTransitionCoordinator
13931a217290cf376d0573fc36e21c8940987485019George Mount     * or ExitTransitionCoordinator) after the shared elements have
14031a217290cf376d0573fc36e21c8940987485019George Mount     * become stationary (shared element transition completes). This tells
14131a217290cf376d0573fc36e21c8940987485019George Mount     * the remote coordinator to take control of the shared elements and
14231a217290cf376d0573fc36e21c8940987485019George Mount     * that animations may begin. The remote Activity won't start entering
14331a217290cf376d0573fc36e21c8940987485019George Mount     * until this message is received, but may wait for
14431a217290cf376d0573fc36e21c8940987485019George Mount     * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true.
14531a217290cf376d0573fc36e21c8940987485019George Mount     */
14662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public static final int MSG_SET_REMOTE_RECEIVER = 100;
14731a217290cf376d0573fc36e21c8940987485019George Mount
14831a217290cf376d0573fc36e21c8940987485019George Mount    /**
14931a217290cf376d0573fc36e21c8940987485019George Mount     * Sent by the entering coordinator to tell the exiting coordinator
15031a217290cf376d0573fc36e21c8940987485019George Mount     * to hide its shared elements after it has started its shared
15131a217290cf376d0573fc36e21c8940987485019George Mount     * element transition. This is temporary until the
15231a217290cf376d0573fc36e21c8940987485019George Mount     * interlock of shared elements is figured out.
15331a217290cf376d0573fc36e21c8940987485019George Mount     */
15431a217290cf376d0573fc36e21c8940987485019George Mount    public static final int MSG_HIDE_SHARED_ELEMENTS = 101;
15531a217290cf376d0573fc36e21c8940987485019George Mount
15631a217290cf376d0573fc36e21c8940987485019George Mount    /**
15731a217290cf376d0573fc36e21c8940987485019George Mount     * Sent by the exiting Activity in ActivityOptions#dispatchActivityStopped
15831a217290cf376d0573fc36e21c8940987485019George Mount     * to leave the Activity in a good state after it has been hidden.
15931a217290cf376d0573fc36e21c8940987485019George Mount     */
16062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public static final int MSG_ACTIVITY_STOPPED = 102;
16131a217290cf376d0573fc36e21c8940987485019George Mount
16231a217290cf376d0573fc36e21c8940987485019George Mount    /**
16331a217290cf376d0573fc36e21c8940987485019George Mount     * Sent by the exiting coordinator (either EnterTransitionCoordinator
16431a217290cf376d0573fc36e21c8940987485019George Mount     * or ExitTransitionCoordinator) after the shared elements have
16531a217290cf376d0573fc36e21c8940987485019George Mount     * become stationary (shared element transition completes). This tells
16631a217290cf376d0573fc36e21c8940987485019George Mount     * the remote coordinator to take control of the shared elements and
16731a217290cf376d0573fc36e21c8940987485019George Mount     * that animations may begin. The remote Activity won't start entering
16831a217290cf376d0573fc36e21c8940987485019George Mount     * until this message is received, but may wait for
16931a217290cf376d0573fc36e21c8940987485019George Mount     * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true.
17031a217290cf376d0573fc36e21c8940987485019George Mount     */
17162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public static final int MSG_TAKE_SHARED_ELEMENTS = 103;
17231a217290cf376d0573fc36e21c8940987485019George Mount
17331a217290cf376d0573fc36e21c8940987485019George Mount    /**
17431a217290cf376d0573fc36e21c8940987485019George Mount     * Sent by the exiting coordinator (either
17531a217290cf376d0573fc36e21c8940987485019George Mount     * EnterTransitionCoordinator or ExitTransitionCoordinator) after
17631a217290cf376d0573fc36e21c8940987485019George Mount     * the exiting Views have finished leaving the scene. This will
17731a217290cf376d0573fc36e21c8940987485019George Mount     * be ignored if allowOverlappingTransitions() is true on the
17831a217290cf376d0573fc36e21c8940987485019George Mount     * remote coordinator. If it is false, it will trigger the enter
17931a217290cf376d0573fc36e21c8940987485019George Mount     * transition to start.
18031a217290cf376d0573fc36e21c8940987485019George Mount     */
18162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public static final int MSG_EXIT_TRANSITION_COMPLETE = 104;
18231a217290cf376d0573fc36e21c8940987485019George Mount
18331a217290cf376d0573fc36e21c8940987485019George Mount    /**
18431a217290cf376d0573fc36e21c8940987485019George Mount     * Sent by Activity#startActivity to begin the exit transition.
18531a217290cf376d0573fc36e21c8940987485019George Mount     */
18662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public static final int MSG_START_EXIT_TRANSITION = 105;
18731a217290cf376d0573fc36e21c8940987485019George Mount
18831a217290cf376d0573fc36e21c8940987485019George Mount    /**
18962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount     * It took too long for a message from the entering Activity, so we canceled the transition.
19031a217290cf376d0573fc36e21c8940987485019George Mount     */
19162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public static final int MSG_CANCEL = 106;
19262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount
193c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    /**
194c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * When returning, this is the destination location for the shared element.
195c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     */
196c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    public static final int MSG_SHARED_ELEMENT_DESTINATION = 107;
197c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
198d265bd7446e662c9597226c596e8f91eda824982George Mount    /**
199d265bd7446e662c9597226c596e8f91eda824982George Mount     * Send the shared element positions.
200d265bd7446e662c9597226c596e8f91eda824982George Mount     */
201d265bd7446e662c9597226c596e8f91eda824982George Mount    public static final int MSG_SEND_SHARED_ELEMENT_DESTINATION = 108;
202d265bd7446e662c9597226c596e8f91eda824982George Mount
20362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    final private Window mWindow;
20462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    final protected ArrayList<String> mAllSharedElementNames;
20562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    final protected ArrayList<View> mSharedElements = new ArrayList<View>();
20662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    final protected ArrayList<String> mSharedElementNames = new ArrayList<String>();
20762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    final protected ArrayList<View> mTransitioningViews = new ArrayList<View>();
20862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    final protected SharedElementListener mListener;
20962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected ResultReceiver mResultReceiver;
21062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    final private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback();
211c9b6df8fa4df3968b2420a52c5281b4765478f68George Mount    final protected boolean mIsReturning;
21262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount
21362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public ActivityTransitionCoordinator(Window window,
21462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            ArrayList<String> allSharedElementNames,
21562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            ArrayList<String> accepted, ArrayList<String> localNames,
216c9b6df8fa4df3968b2420a52c5281b4765478f68George Mount            SharedElementListener listener, boolean isReturning) {
2178c2614ce4328640642d8e8be437859e0508a39b4George Mount        this(window, allSharedElementNames, listener, isReturning);
2188c2614ce4328640642d8e8be437859e0508a39b4George Mount        viewsReady(accepted, localNames);
2198c2614ce4328640642d8e8be437859e0508a39b4George Mount    }
2208c2614ce4328640642d8e8be437859e0508a39b4George Mount
2218c2614ce4328640642d8e8be437859e0508a39b4George Mount    public ActivityTransitionCoordinator(Window window,
2228c2614ce4328640642d8e8be437859e0508a39b4George Mount            ArrayList<String> allSharedElementNames,
2238c2614ce4328640642d8e8be437859e0508a39b4George Mount            SharedElementListener listener, boolean isReturning) {
22462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        super(new Handler());
22562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        mWindow = window;
22662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        mListener = listener;
22762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        mAllSharedElementNames = allSharedElementNames;
228c9b6df8fa4df3968b2420a52c5281b4765478f68George Mount        mIsReturning = isReturning;
2298c2614ce4328640642d8e8be437859e0508a39b4George Mount    }
2308c2614ce4328640642d8e8be437859e0508a39b4George Mount
2318c2614ce4328640642d8e8be437859e0508a39b4George Mount    protected void viewsReady(ArrayList<String> accepted, ArrayList<String> localNames) {
23262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        setSharedElements(accepted, localNames);
23331a217290cf376d0573fc36e21c8940987485019George Mount        if (getViewsTransition() != null) {
23462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            getDecor().captureTransitioningViews(mTransitioningViews);
23562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            mTransitioningViews.removeAll(mSharedElements);
23631a217290cf376d0573fc36e21c8940987485019George Mount        }
23762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        setEpicenter();
23831a217290cf376d0573fc36e21c8940987485019George Mount    }
23931a217290cf376d0573fc36e21c8940987485019George Mount
24031a217290cf376d0573fc36e21c8940987485019George Mount    protected Window getWindow() {
24131a217290cf376d0573fc36e21c8940987485019George Mount        return mWindow;
24231a217290cf376d0573fc36e21c8940987485019George Mount    }
24331a217290cf376d0573fc36e21c8940987485019George Mount
24431a217290cf376d0573fc36e21c8940987485019George Mount    protected ViewGroup getDecor() {
24531a217290cf376d0573fc36e21c8940987485019George Mount        return (mWindow == null) ? null : (ViewGroup) mWindow.getDecorView();
24631a217290cf376d0573fc36e21c8940987485019George Mount    }
24731a217290cf376d0573fc36e21c8940987485019George Mount
24862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    /**
24962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount     * Sets the transition epicenter to the position of the first shared element.
25062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount     */
25162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected void setEpicenter() {
25262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        View epicenter = null;
25362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        if (!mAllSharedElementNames.isEmpty() && !mSharedElementNames.isEmpty() &&
25462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                mAllSharedElementNames.get(0).equals(mSharedElementNames.get(0))) {
25562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            epicenter = mSharedElements.get(0);
25631a217290cf376d0573fc36e21c8940987485019George Mount        }
25762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        setEpicenter(epicenter);
25831a217290cf376d0573fc36e21c8940987485019George Mount    }
25931a217290cf376d0573fc36e21c8940987485019George Mount
26062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    private void setEpicenter(View view) {
26162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        if (view == null) {
26262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            mEpicenterCallback.setEpicenter(null);
26331a217290cf376d0573fc36e21c8940987485019George Mount        } else {
2648e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount            Rect epicenter = new Rect();
2658e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount            view.getBoundsOnScreen(epicenter);
26662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            mEpicenterCallback.setEpicenter(epicenter);
26731a217290cf376d0573fc36e21c8940987485019George Mount        }
26831a217290cf376d0573fc36e21c8940987485019George Mount    }
26931a217290cf376d0573fc36e21c8940987485019George Mount
27062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public ArrayList<String> getAcceptedNames() {
27162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        return mSharedElementNames;
27231a217290cf376d0573fc36e21c8940987485019George Mount    }
27331a217290cf376d0573fc36e21c8940987485019George Mount
27462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    public ArrayList<String> getMappedNames() {
27562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        ArrayList<String> names = new ArrayList<String>(mSharedElements.size());
27662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        for (int i = 0; i < mSharedElements.size(); i++) {
27762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            names.add(mSharedElements.get(i).getViewName());
278080443bcb63418245c2408500db735fece5e7083George Mount        }
27962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        return names;
28031a217290cf376d0573fc36e21c8940987485019George Mount    }
28131a217290cf376d0573fc36e21c8940987485019George Mount
2828c2614ce4328640642d8e8be437859e0508a39b4George Mount    public ArrayList<String> getAllSharedElementNames() { return mAllSharedElementNames; }
2838c2614ce4328640642d8e8be437859e0508a39b4George Mount
28431a217290cf376d0573fc36e21c8940987485019George Mount    public static void setViewVisibility(Collection<View> views, int visibility) {
28531a217290cf376d0573fc36e21c8940987485019George Mount        if (views != null) {
28631a217290cf376d0573fc36e21c8940987485019George Mount            for (View view : views) {
28731a217290cf376d0573fc36e21c8940987485019George Mount                view.setVisibility(visibility);
28831a217290cf376d0573fc36e21c8940987485019George Mount            }
28931a217290cf376d0573fc36e21c8940987485019George Mount        }
29031a217290cf376d0573fc36e21c8940987485019George Mount    }
29131a217290cf376d0573fc36e21c8940987485019George Mount
29262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static Transition addTargets(Transition transition, Collection<View> views) {
29331a217290cf376d0573fc36e21c8940987485019George Mount        if (transition == null || views == null || views.isEmpty()) {
29431a217290cf376d0573fc36e21c8940987485019George Mount            return null;
29531a217290cf376d0573fc36e21c8940987485019George Mount        }
29631a217290cf376d0573fc36e21c8940987485019George Mount        TransitionSet set = new TransitionSet();
29762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        set.addTransition(transition);
29831a217290cf376d0573fc36e21c8940987485019George Mount        if (views != null) {
29931a217290cf376d0573fc36e21c8940987485019George Mount            for (View view: views) {
30031a217290cf376d0573fc36e21c8940987485019George Mount                set.addTarget(view);
30131a217290cf376d0573fc36e21c8940987485019George Mount            }
30231a217290cf376d0573fc36e21c8940987485019George Mount        }
30331a217290cf376d0573fc36e21c8940987485019George Mount        return set;
30431a217290cf376d0573fc36e21c8940987485019George Mount    }
30531a217290cf376d0573fc36e21c8940987485019George Mount
30662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected Transition configureTransition(Transition transition) {
30731a217290cf376d0573fc36e21c8940987485019George Mount        if (transition != null) {
30862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            transition = transition.clone();
30962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            transition.setEpicenterCallback(mEpicenterCallback);
31031a217290cf376d0573fc36e21c8940987485019George Mount        }
31131a217290cf376d0573fc36e21c8940987485019George Mount        return transition;
31231a217290cf376d0573fc36e21c8940987485019George Mount    }
31331a217290cf376d0573fc36e21c8940987485019George Mount
31462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected static Transition mergeTransitions(Transition transition1, Transition transition2) {
31562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        if (transition1 == null) {
31662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            return transition2;
31762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        } else if (transition2 == null) {
31862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            return transition1;
31962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        } else {
32062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            TransitionSet transitionSet = new TransitionSet();
32162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            transitionSet.addTransition(transition1);
32262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            transitionSet.addTransition(transition2);
32362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            return transitionSet;
32462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        }
32562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    }
32662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount
32762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    private void setSharedElements(ArrayList<String> accepted, ArrayList<String> localNames) {
32862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        if (!mAllSharedElementNames.isEmpty()) {
32962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
33062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            getDecor().findNamedViews(sharedElements);
33162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            if (accepted != null) {
33262ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                for (int i = 0; i < localNames.size(); i++) {
33362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                    String localName = localNames.get(i);
33462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                    String acceptedName = accepted.get(i);
33562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                    if (!localName.equals(acceptedName)) {
33662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                        View view = sharedElements.remove(localName);
33762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                        if (view != null) {
33862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                            sharedElements.put(acceptedName, view);
33962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                        }
34062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                    }
341caa03107d4322b0e30f92e6dc1eb1ea73b1bf747George Mount                }
342caa03107d4322b0e30f92e6dc1eb1ea73b1bf747George Mount            }
34362ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            sharedElements.retainAll(mAllSharedElementNames);
34462ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            mListener.remapSharedElements(mAllSharedElementNames, sharedElements);
34562ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            sharedElements.retainAll(mAllSharedElementNames);
34662ab9b78b77b7dd851c47115f4d8d7611d657585George Mount            for (int i = 0; i < mAllSharedElementNames.size(); i++) {
34762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                String name = mAllSharedElementNames.get(i);
34862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                View sharedElement = sharedElements.get(name);
34962ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                if (sharedElement != null) {
35062ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                    mSharedElementNames.add(name);
35162ab9b78b77b7dd851c47115f4d8d7611d657585George Mount                    mSharedElements.add(sharedElement);
352caa03107d4322b0e30f92e6dc1eb1ea73b1bf747George Mount                }
353caa03107d4322b0e30f92e6dc1eb1ea73b1bf747George Mount            }
354caa03107d4322b0e30f92e6dc1eb1ea73b1bf747George Mount        }
355caa03107d4322b0e30f92e6dc1eb1ea73b1bf747George Mount    }
356caa03107d4322b0e30f92e6dc1eb1ea73b1bf747George Mount
35762ab9b78b77b7dd851c47115f4d8d7611d657585George Mount    protected void setResultReceiver(ResultReceiver resultReceiver) {
35862ab9b78b77b7dd851c47115f4d8d7611d657585George Mount        mResultReceiver = resultReceiver;
359080443bcb63418245c2408500db735fece5e7083George Mount    }
360080443bcb63418245c2408500db735fece5e7083George Mount
361a712e8cc2f16ac32ee5f1bbf5b962969f2f3451eGeorge Mount    protected abstract Transition getViewsTransition();
362080443bcb63418245c2408500db735fece5e7083George Mount
363c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    private static void setSharedElementState(View view, String name, Bundle transitionArgs,
364c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            int[] parentLoc) {
365c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        Bundle sharedElementBundle = transitionArgs.getBundle(name);
366c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (sharedElementBundle == null) {
367c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            return;
368c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
369c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
370c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (view instanceof ImageView) {
371c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            int scaleTypeInt = sharedElementBundle.getInt(KEY_SCALE_TYPE, -1);
372c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            if (scaleTypeInt >= 0) {
373c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                ImageView imageView = (ImageView) view;
374c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                ImageView.ScaleType scaleType = SCALE_TYPE_VALUES[scaleTypeInt];
375c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                imageView.setScaleType(scaleType);
376c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                if (scaleType == ImageView.ScaleType.MATRIX) {
377c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                    float[] matrixValues = sharedElementBundle.getFloatArray(KEY_IMAGE_MATRIX);
378c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                    Matrix matrix = new Matrix();
379c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                    matrix.setValues(matrixValues);
380c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                    imageView.setImageMatrix(matrix);
381c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                }
382c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            }
383c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
384c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
385c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
386c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        view.setTranslationZ(z);
387c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
388c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int x = sharedElementBundle.getInt(KEY_SCREEN_X);
389c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int y = sharedElementBundle.getInt(KEY_SCREEN_Y);
390c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int width = sharedElementBundle.getInt(KEY_WIDTH);
391c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int height = sharedElementBundle.getInt(KEY_HEIGHT);
392c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
393c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
394c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
395c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        view.measure(widthSpec, heightSpec);
396c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
397c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int left = x - parentLoc[0];
398c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int top = y - parentLoc[1];
399c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int right = left + width;
400c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int bottom = top + height;
401c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        view.layout(left, top, right, bottom);
402c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
403c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
404c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    protected ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> setSharedElementState(
405c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            Bundle sharedElementState, final ArrayList<View> snapshots) {
406c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> originalImageState =
407c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                new ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>>();
408c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (sharedElementState != null) {
409c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            int[] tempLoc = new int[2];
410c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            for (int i = 0; i < mSharedElementNames.size(); i++) {
411c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                View sharedElement = mSharedElements.get(i);
412c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                String name = mSharedElementNames.get(i);
413c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                Pair<ImageView.ScaleType, Matrix> originalState = getOldImageState(sharedElement,
414c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                        name, sharedElementState);
415c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                if (originalState != null) {
416c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                    originalImageState.put((ImageView) sharedElement, originalState);
417c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                }
418c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                View parent = (View) sharedElement.getParent();
419c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                parent.getLocationOnScreen(tempLoc);
420c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                setSharedElementState(sharedElement, name, sharedElementState, tempLoc);
421c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            }
422c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
423c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        mListener.setSharedElementStart(mSharedElementNames, mSharedElements, snapshots);
424c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
425c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        getDecor().getViewTreeObserver().addOnPreDrawListener(
426c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                new ViewTreeObserver.OnPreDrawListener() {
427c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                    @Override
428c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                    public boolean onPreDraw() {
429c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                        getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
430c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                        mListener.setSharedElementEnd(mSharedElementNames, mSharedElements,
431c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                                snapshots);
432c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                        return true;
433c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                    }
434c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                }
435c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        );
436c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        return originalImageState;
437c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
438c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
439c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    private static Pair<ImageView.ScaleType, Matrix> getOldImageState(View view, String name,
440c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            Bundle transitionArgs) {
441c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (!(view instanceof ImageView)) {
442c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            return null;
443c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
444c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        Bundle bundle = transitionArgs.getBundle(name);
445c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (bundle == null) {
446c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            return null;
447c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
448c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int scaleTypeInt = bundle.getInt(KEY_SCALE_TYPE, -1);
449c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (scaleTypeInt < 0) {
450c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            return null;
451c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
452c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
453c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        ImageView imageView = (ImageView) view;
454c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        ImageView.ScaleType originalScaleType = imageView.getScaleType();
455c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
456c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        Matrix originalMatrix = null;
457c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (originalScaleType == ImageView.ScaleType.MATRIX) {
458c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            originalMatrix = new Matrix(imageView.getImageMatrix());
459c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
460c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
461c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        return Pair.create(originalScaleType, originalMatrix);
462c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
463c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
464c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    protected ArrayList<View> createSnapshots(Bundle state, Collection<String> names) {
465c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int numSharedElements = names.size();
466c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (numSharedElements == 0) {
467c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            return null;
468c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
469c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        ArrayList<View> snapshots = new ArrayList<View>(numSharedElements);
470c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        Context context = getWindow().getContext();
471c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        int[] parentLoc = new int[2];
472c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        getDecor().getLocationOnScreen(parentLoc);
473c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        for (String name: names) {
474c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            Bundle sharedElementBundle = state.getBundle(name);
475c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            if (sharedElementBundle != null) {
476c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                Bitmap bitmap = sharedElementBundle.getParcelable(KEY_BITMAP);
477c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                View snapshot = new View(context);
478c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                Resources resources = getWindow().getContext().getResources();
479c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                if (bitmap != null) {
480c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                    snapshot.setBackground(new BitmapDrawable(resources, bitmap));
481c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                }
482c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                snapshot.setViewName(name);
483c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                setSharedElementState(snapshot, name, state, parentLoc);
484c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                snapshots.add(snapshot);
485c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            }
486c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
487c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        return snapshots;
488c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
489c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
490c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    protected static void setOriginalImageViewState(
491c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> originalState) {
492c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        for (int i = 0; i < originalState.size(); i++) {
493c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            ImageView imageView = originalState.keyAt(i);
494c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            Pair<ImageView.ScaleType, Matrix> state = originalState.valueAt(i);
495c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            imageView.setScaleType(state.first);
496c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            imageView.setImageMatrix(state.second);
497c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
498c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
499c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
500c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    protected Bundle captureSharedElementState() {
501c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        Bundle bundle = new Bundle();
5028e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount        Rect tempBounds = new Rect();
503c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        for (int i = 0; i < mSharedElementNames.size(); i++) {
504c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            View sharedElement = mSharedElements.get(i);
505c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            String name = mSharedElementNames.get(i);
5068e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount            captureSharedElementState(sharedElement, name, bundle, tempBounds);
507c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
508c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        return bundle;
509c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
510c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
511c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    /**
512c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * Captures placement information for Views with a shared element name for
513c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * Activity Transitions.
514c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     *
515c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * @param view           The View to capture the placement information for.
516c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * @param name           The shared element name in the target Activity to apply the placement
517c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     *                       information for.
518c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     * @param transitionArgs Bundle to store shared element placement information.
5198e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount     * @param tempBounds     A temporary Rect for capturing the current location of views.
520c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount     */
521c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    private static void captureSharedElementState(View view, String name, Bundle transitionArgs,
5228e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount            Rect tempBounds) {
523c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        Bundle sharedElementBundle = new Bundle();
5248e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount        tempBounds.set(0, 0, view.getWidth(), view.getHeight());
5258e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount        view.getBoundsOnScreen(tempBounds);
5268e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount        sharedElementBundle.putInt(KEY_SCREEN_X, tempBounds.left);
5278e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount        int width = tempBounds.width();
528c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        sharedElementBundle.putInt(KEY_WIDTH, width);
529c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
5308e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount        sharedElementBundle.putInt(KEY_SCREEN_Y, tempBounds.top);
5318e43d6d62fb3a94b2a7175d1dee3174c62f217baGeorge Mount        int height = tempBounds.height();
532c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        sharedElementBundle.putInt(KEY_HEIGHT, height);
533c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
534c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ());
535c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
536c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (width > 0 && height > 0) {
537c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
538c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            Canvas canvas = new Canvas(bitmap);
539c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            view.draw(canvas);
540c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            sharedElementBundle.putParcelable(KEY_BITMAP, bitmap);
541c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
542c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
543c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        if (view instanceof ImageView) {
544c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            ImageView imageView = (ImageView) view;
545c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            int scaleTypeInt = scaleTypeToInt(imageView.getScaleType());
546c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            sharedElementBundle.putInt(KEY_SCALE_TYPE, scaleTypeInt);
547c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            if (imageView.getScaleType() == ImageView.ScaleType.MATRIX) {
548c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                float[] matrix = new float[9];
549c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                imageView.getImageMatrix().getValues(matrix);
550c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                sharedElementBundle.putFloatArray(KEY_IMAGE_MATRIX, matrix);
551c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            }
552c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
553c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
554c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        transitionArgs.putBundle(name, sharedElementBundle);
555c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
556c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
557c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    private static int scaleTypeToInt(ImageView.ScaleType scaleType) {
558c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        for (int i = 0; i < SCALE_TYPE_VALUES.length; i++) {
559c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            if (scaleType == SCALE_TYPE_VALUES[i]) {
560c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount                return i;
561c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount            }
562c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        }
563c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount        return -1;
564c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount    }
565c93ca1617397aace8449f88d1a1e94ec704a2ef4George Mount
56631a217290cf376d0573fc36e21c8940987485019George Mount    private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
56731a217290cf376d0573fc36e21c8940987485019George Mount        private Rect mEpicenter;
56831a217290cf376d0573fc36e21c8940987485019George Mount
56931a217290cf376d0573fc36e21c8940987485019George Mount        public void setEpicenter(Rect epicenter) { mEpicenter = epicenter; }
57031a217290cf376d0573fc36e21c8940987485019George Mount
57131a217290cf376d0573fc36e21c8940987485019George Mount        @Override
572dc21d3b2804c24fe29ec860796d11185901364c4George Mount        public Rect onGetEpicenter(Transition transition) {
57331a217290cf376d0573fc36e21c8940987485019George Mount            return mEpicenter;
57431a217290cf376d0573fc36e21c8940987485019George Mount        }
57531a217290cf376d0573fc36e21c8940987485019George Mount    }
576800d72b0e05049e4a8f90ea96ec165fc975264ceGeorge Mount
57731a217290cf376d0573fc36e21c8940987485019George Mount}
578