blob: 540376ec5fb726f031e99e7c40de48f6fe261cd1 [file] [log] [blame]
George Mount31a21722014-03-24 17:44:36 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.app;
17
George Mountc93ca162014-05-23 19:21:36 -070018import android.content.Context;
George Mountc93ca162014-05-23 19:21:36 -070019import android.graphics.Matrix;
George Mount31a21722014-03-24 17:44:36 -070020import android.graphics.Rect;
Dake Gu7bf379c2014-07-15 16:29:38 -070021import android.graphics.RectF;
George Mountc93ca162014-05-23 19:21:36 -070022import android.os.Bundle;
George Mount31a21722014-03-24 17:44:36 -070023import android.os.Handler;
George Mount480ca822014-08-08 16:35:48 -070024import android.os.Parcelable;
George Mount31a21722014-03-24 17:44:36 -070025import android.os.ResultReceiver;
26import android.transition.Transition;
George Mount31a21722014-03-24 17:44:36 -070027import android.transition.TransitionSet;
28import android.util.ArrayMap;
George Mountfe361d22014-07-08 17:25:25 -070029import android.view.GhostView;
George Mount31a21722014-03-24 17:44:36 -070030import android.view.View;
31import android.view.ViewGroup;
George Mountfe361d22014-07-08 17:25:25 -070032import android.view.ViewGroupOverlay;
33import android.view.ViewParent;
George Mountc93ca162014-05-23 19:21:36 -070034import android.view.ViewTreeObserver;
George Mount31a21722014-03-24 17:44:36 -070035import android.view.Window;
George Mountcaa03102014-04-15 09:01:32 -070036import android.widget.ImageView;
George Mount31a21722014-03-24 17:44:36 -070037
38import java.util.ArrayList;
39import java.util.Collection;
40
41/**
42 * Base class for ExitTransitionCoordinator and EnterTransitionCoordinator, classes
43 * that manage activity transitions and the communications coordinating them between
44 * Activities. The ExitTransitionCoordinator is created in the
45 * ActivityOptions#makeSceneTransitionAnimation. The EnterTransitionCoordinator
46 * is created by ActivityOptions#createEnterActivityTransition by Activity when the window is
47 * attached.
48 *
49 * Typical startActivity goes like this:
50 * 1) ExitTransitionCoordinator created with ActivityOptions#makeSceneTransitionAnimation
51 * 2) Activity#startActivity called and that calls startExit() through
52 * ActivityOptions#dispatchStartExit
53 * - Exit transition starts by setting transitioning Views to INVISIBLE
54 * 3) Launched Activity starts, creating an EnterTransitionCoordinator.
55 * - The Window is made translucent
56 * - The Window background alpha is set to 0
57 * - The transitioning views are made INVISIBLE
58 * - MSG_SET_LISTENER is sent back to the ExitTransitionCoordinator.
59 * 4) The shared element transition completes.
60 * - MSG_TAKE_SHARED_ELEMENTS is sent to the EnterTransitionCoordinator
61 * 5) The MSG_TAKE_SHARED_ELEMENTS is received by the EnterTransitionCoordinator.
62 * - Shared elements are made VISIBLE
63 * - Shared elements positions and size are set to match the end state of the calling
64 * Activity.
65 * - The shared element transition is started
66 * - If the window allows overlapping transitions, the views transition is started by setting
67 * the entering Views to VISIBLE and the background alpha is animated to opaque.
68 * - MSG_HIDE_SHARED_ELEMENTS is sent to the ExitTransitionCoordinator
69 * 6) MSG_HIDE_SHARED_ELEMENTS is received by the ExitTransitionCoordinator
70 * - The shared elements are made INVISIBLE
71 * 7) The exit transition completes in the calling Activity.
72 * - MSG_EXIT_TRANSITION_COMPLETE is sent to the EnterTransitionCoordinator.
73 * 8) The MSG_EXIT_TRANSITION_COMPLETE is received by the EnterTransitionCoordinator.
74 * - If the window doesn't allow overlapping enter transitions, the enter transition is started
75 * by setting entering views to VISIBLE and the background is animated to opaque.
76 * 9) The background opacity animation completes.
77 * - The window is made opaque
78 * 10) The calling Activity gets an onStop() call
79 * - onActivityStopped() is called and all exited Views are made VISIBLE.
80 *
Craig Mautner73f843d2014-05-19 09:42:28 -070081 * Typical finishAfterTransition goes like this:
82 * 1) finishAfterTransition() creates an ExitTransitionCoordinator and calls startExit()
George Mount62ab9b72014-05-02 13:51:17 -070083 * - The Window start transitioning to Translucent with a new ActivityOptions.
George Mount31a21722014-03-24 17:44:36 -070084 * - If no background exists, a black background is substituted
George Mount31a21722014-03-24 17:44:36 -070085 * - The shared elements in the scene are matched against those shared elements
86 * that were sent by comparing the names.
87 * - The exit transition is started by setting Views to INVISIBLE.
George Mount62ab9b72014-05-02 13:51:17 -070088 * 2) The ActivityOptions is received by the Activity and an EnterTransitionCoordinator is created.
George Mount31a21722014-03-24 17:44:36 -070089 * - All transitioning views are made VISIBLE to reverse what was done when onActivityStopped()
90 * was called
91 * 3) The Window is made translucent and a callback is received
92 * - The background alpha is animated to 0
93 * 4) The background alpha animation completes
94 * 5) The shared element transition completes
95 * - After both 4 & 5 complete, MSG_TAKE_SHARED_ELEMENTS is sent to the
George Mount62ab9b72014-05-02 13:51:17 -070096 * EnterTransitionCoordinator
97 * 6) MSG_TAKE_SHARED_ELEMENTS is received by EnterTransitionCoordinator
George Mount31a21722014-03-24 17:44:36 -070098 * - Shared elements are made VISIBLE
99 * - Shared elements positions and size are set to match the end state of the calling
100 * Activity.
101 * - The shared element transition is started
102 * - If the window allows overlapping transitions, the views transition is started by setting
103 * the entering Views to VISIBLE.
George Mount62ab9b72014-05-02 13:51:17 -0700104 * - MSG_HIDE_SHARED_ELEMENTS is sent to the ExitTransitionCoordinator
105 * 7) MSG_HIDE_SHARED_ELEMENTS is received by the ExitTransitionCoordinator
George Mount31a21722014-03-24 17:44:36 -0700106 * - The shared elements are made INVISIBLE
107 * 8) The exit transition completes in the finishing Activity.
George Mount62ab9b72014-05-02 13:51:17 -0700108 * - MSG_EXIT_TRANSITION_COMPLETE is sent to the EnterTransitionCoordinator.
George Mount31a21722014-03-24 17:44:36 -0700109 * - finish() is called on the exiting Activity
George Mount62ab9b72014-05-02 13:51:17 -0700110 * 9) The MSG_EXIT_TRANSITION_COMPLETE is received by the EnterTransitionCoordinator.
George Mount31a21722014-03-24 17:44:36 -0700111 * - If the window doesn't allow overlapping enter transitions, the enter transition is started
112 * by setting entering views to VISIBLE.
113 */
114abstract class ActivityTransitionCoordinator extends ResultReceiver {
115 private static final String TAG = "ActivityTransitionCoordinator";
116
117 /**
George Mount31a21722014-03-24 17:44:36 -0700118 * For Activity transitions, the called Activity's listener to receive calls
119 * when transitions complete.
120 */
George Mount62ab9b72014-05-02 13:51:17 -0700121 static final String KEY_REMOTE_RECEIVER = "android:remoteReceiver";
George Mount31a21722014-03-24 17:44:36 -0700122
Dake Gu7bf379c2014-07-15 16:29:38 -0700123 protected static final String KEY_SCREEN_LEFT = "shared_element:screenLeft";
124 protected static final String KEY_SCREEN_TOP = "shared_element:screenTop";
125 protected static final String KEY_SCREEN_RIGHT = "shared_element:screenRight";
126 protected static final String KEY_SCREEN_BOTTOM= "shared_element:screenBottom";
George Mount62ab9b72014-05-02 13:51:17 -0700127 protected static final String KEY_TRANSLATION_Z = "shared_element:translationZ";
George Mount480ca822014-08-08 16:35:48 -0700128 protected static final String KEY_SNAPSHOT = "shared_element:bitmap";
George Mount62ab9b72014-05-02 13:51:17 -0700129 protected static final String KEY_SCALE_TYPE = "shared_element:scaleType";
130 protected static final String KEY_IMAGE_MATRIX = "shared_element:imageMatrix";
George Mount26c82b62014-08-08 15:43:59 -0700131 protected static final String KEY_ELEVATION = "shared_element:elevation";
George Mount080443b2014-05-05 10:47:00 -0700132
George Mount62ab9b72014-05-02 13:51:17 -0700133 protected static final ImageView.ScaleType[] SCALE_TYPE_VALUES = ImageView.ScaleType.values();
George Mount31a21722014-03-24 17:44:36 -0700134
135 /**
136 * Sent by the exiting coordinator (either EnterTransitionCoordinator
137 * or ExitTransitionCoordinator) after the shared elements have
138 * become stationary (shared element transition completes). This tells
139 * the remote coordinator to take control of the shared elements and
140 * that animations may begin. The remote Activity won't start entering
141 * until this message is received, but may wait for
142 * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true.
143 */
George Mount62ab9b72014-05-02 13:51:17 -0700144 public static final int MSG_SET_REMOTE_RECEIVER = 100;
George Mount31a21722014-03-24 17:44:36 -0700145
146 /**
147 * Sent by the entering coordinator to tell the exiting coordinator
148 * to hide its shared elements after it has started its shared
149 * element transition. This is temporary until the
150 * interlock of shared elements is figured out.
151 */
152 public static final int MSG_HIDE_SHARED_ELEMENTS = 101;
153
154 /**
George Mount31a21722014-03-24 17:44:36 -0700155 * Sent by the exiting coordinator (either EnterTransitionCoordinator
156 * or ExitTransitionCoordinator) after the shared elements have
157 * become stationary (shared element transition completes). This tells
158 * the remote coordinator to take control of the shared elements and
159 * that animations may begin. The remote Activity won't start entering
160 * until this message is received, but may wait for
161 * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true.
162 */
George Mount62ab9b72014-05-02 13:51:17 -0700163 public static final int MSG_TAKE_SHARED_ELEMENTS = 103;
George Mount31a21722014-03-24 17:44:36 -0700164
165 /**
166 * Sent by the exiting coordinator (either
167 * EnterTransitionCoordinator or ExitTransitionCoordinator) after
168 * the exiting Views have finished leaving the scene. This will
169 * be ignored if allowOverlappingTransitions() is true on the
170 * remote coordinator. If it is false, it will trigger the enter
171 * transition to start.
172 */
George Mount62ab9b72014-05-02 13:51:17 -0700173 public static final int MSG_EXIT_TRANSITION_COMPLETE = 104;
George Mount31a21722014-03-24 17:44:36 -0700174
175 /**
176 * Sent by Activity#startActivity to begin the exit transition.
177 */
George Mount62ab9b72014-05-02 13:51:17 -0700178 public static final int MSG_START_EXIT_TRANSITION = 105;
George Mount31a21722014-03-24 17:44:36 -0700179
George Mount62ab9b72014-05-02 13:51:17 -0700180 /**
181 * It took too long for a message from the entering Activity, so we canceled the transition.
182 */
183 public static final int MSG_CANCEL = 106;
George Mount31a21722014-03-24 17:44:36 -0700184
George Mountc93ca162014-05-23 19:21:36 -0700185 /**
186 * When returning, this is the destination location for the shared element.
187 */
188 public static final int MSG_SHARED_ELEMENT_DESTINATION = 107;
189
George Mountd265bd72014-06-02 07:22:59 -0700190 /**
191 * Send the shared element positions.
192 */
193 public static final int MSG_SEND_SHARED_ELEMENT_DESTINATION = 108;
194
George Mounta0a02602014-06-20 18:22:26 -0700195 private Window mWindow;
George Mount62ab9b72014-05-02 13:51:17 -0700196 final protected ArrayList<String> mAllSharedElementNames;
197 final protected ArrayList<View> mSharedElements = new ArrayList<View>();
198 final protected ArrayList<String> mSharedElementNames = new ArrayList<String>();
George Mountb694e082014-09-12 07:34:52 -0700199 protected ArrayList<View> mTransitioningViews = new ArrayList<View>();
George Mount65580562014-08-29 08:15:48 -0700200 protected SharedElementCallback mListener;
George Mount62ab9b72014-05-02 13:51:17 -0700201 protected ResultReceiver mResultReceiver;
202 final private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback();
George Mountc9b6df82014-05-21 15:07:04 -0700203 final protected boolean mIsReturning;
George Mount67d92432014-06-06 13:34:20 -0700204 private Runnable mPendingTransition;
205 private boolean mIsStartingTransition;
George Mountfe361d22014-07-08 17:25:25 -0700206 private ArrayList<GhostViewListeners> mGhostViewListeners =
207 new ArrayList<GhostViewListeners>();
George Mount0f0c4732014-09-05 13:47:47 -0700208 private ArrayMap<View, Float> mOriginalAlphas = new ArrayMap<View, Float>();
George Mount67d92432014-06-06 13:34:20 -0700209
George Mount8c2614c2014-06-10 11:12:01 -0700210 public ActivityTransitionCoordinator(Window window,
211 ArrayList<String> allSharedElementNames,
George Mount65580562014-08-29 08:15:48 -0700212 SharedElementCallback listener, boolean isReturning) {
George Mount31a21722014-03-24 17:44:36 -0700213 super(new Handler());
214 mWindow = window;
George Mount62ab9b72014-05-02 13:51:17 -0700215 mListener = listener;
216 mAllSharedElementNames = allSharedElementNames;
George Mountc9b6df82014-05-21 15:07:04 -0700217 mIsReturning = isReturning;
George Mount8c2614c2014-06-10 11:12:01 -0700218 }
219
George Mount1fecfb22014-06-18 14:55:55 -0700220 protected void viewsReady(ArrayMap<String, View> sharedElements) {
George Mountce725a42014-08-27 16:10:46 -0700221 sharedElements.retainAll(mAllSharedElementNames);
George Mount1732f522014-09-17 16:59:36 -0700222 if (mListener != null) {
223 mListener.onMapSharedElements(mAllSharedElementNames, sharedElements);
224 }
George Mountce725a42014-08-27 16:10:46 -0700225 mSharedElementNames.addAll(sharedElements.keySet());
226 mSharedElements.addAll(sharedElements.values());
George Mountb694e082014-09-12 07:34:52 -0700227 if (getViewsTransition() != null && mTransitioningViews != null) {
George Mount48bd13c2014-09-12 10:54:54 -0700228 ViewGroup decorView = getDecor();
229 if (decorView != null) {
230 decorView.captureTransitioningViews(mTransitioningViews);
231 }
George Mount62ab9b72014-05-02 13:51:17 -0700232 mTransitioningViews.removeAll(mSharedElements);
George Mount31a21722014-03-24 17:44:36 -0700233 }
George Mount62ab9b72014-05-02 13:51:17 -0700234 setEpicenter();
George Mount31a21722014-03-24 17:44:36 -0700235 }
236
George Mount60625b02014-06-24 07:46:23 -0700237 protected void stripOffscreenViews() {
George Mountb694e082014-09-12 07:34:52 -0700238 if (mTransitioningViews == null) {
239 return;
240 }
George Mount60625b02014-06-24 07:46:23 -0700241 Rect r = new Rect();
242 for (int i = mTransitioningViews.size() - 1; i >= 0; i--) {
243 View view = mTransitioningViews.get(i);
244 if (!view.getGlobalVisibleRect(r)) {
245 mTransitioningViews.remove(i);
George Mount653ea662014-09-12 13:56:32 -0700246 showView(view, true);
George Mount60625b02014-06-24 07:46:23 -0700247 }
248 }
249 }
250
George Mount31a21722014-03-24 17:44:36 -0700251 protected Window getWindow() {
252 return mWindow;
253 }
254
George Mounta2bbbb32014-08-12 10:16:20 -0700255 public ViewGroup getDecor() {
George Mount31a21722014-03-24 17:44:36 -0700256 return (mWindow == null) ? null : (ViewGroup) mWindow.getDecorView();
257 }
258
George Mount62ab9b72014-05-02 13:51:17 -0700259 /**
260 * Sets the transition epicenter to the position of the first shared element.
261 */
262 protected void setEpicenter() {
263 View epicenter = null;
George Mountc6186bf2014-09-04 16:33:59 -0700264 if (!mAllSharedElementNames.isEmpty() && !mSharedElementNames.isEmpty()) {
265 int index = mSharedElementNames.indexOf(mAllSharedElementNames.get(0));
266 if (index >= 0) {
267 epicenter = mSharedElements.get(index);
268 }
George Mount31a21722014-03-24 17:44:36 -0700269 }
George Mount62ab9b72014-05-02 13:51:17 -0700270 setEpicenter(epicenter);
George Mount31a21722014-03-24 17:44:36 -0700271 }
272
George Mount62ab9b72014-05-02 13:51:17 -0700273 private void setEpicenter(View view) {
274 if (view == null) {
275 mEpicenterCallback.setEpicenter(null);
George Mount31a21722014-03-24 17:44:36 -0700276 } else {
George Mount8e43d6d2014-06-05 17:25:46 -0700277 Rect epicenter = new Rect();
278 view.getBoundsOnScreen(epicenter);
George Mount62ab9b72014-05-02 13:51:17 -0700279 mEpicenterCallback.setEpicenter(epicenter);
George Mount31a21722014-03-24 17:44:36 -0700280 }
281 }
282
George Mount62ab9b72014-05-02 13:51:17 -0700283 public ArrayList<String> getAcceptedNames() {
284 return mSharedElementNames;
George Mount31a21722014-03-24 17:44:36 -0700285 }
286
George Mount62ab9b72014-05-02 13:51:17 -0700287 public ArrayList<String> getMappedNames() {
288 ArrayList<String> names = new ArrayList<String>(mSharedElements.size());
289 for (int i = 0; i < mSharedElements.size(); i++) {
George Mount0a2ae002014-06-23 14:57:27 +0000290 names.add(mSharedElements.get(i).getTransitionName());
George Mount31a21722014-03-24 17:44:36 -0700291 }
George Mount62ab9b72014-05-02 13:51:17 -0700292 return names;
George Mount31a21722014-03-24 17:44:36 -0700293 }
294
George Mount700db2a2014-07-07 17:17:49 -0700295 public ArrayList<View> copyMappedViews() {
296 return new ArrayList<View>(mSharedElements);
George Mount1fecfb22014-06-18 14:55:55 -0700297 }
298
George Mount8c2614c2014-06-10 11:12:01 -0700299 public ArrayList<String> getAllSharedElementNames() { return mAllSharedElementNames; }
300
George Mount88815022014-06-25 14:33:54 -0700301 protected Transition setTargets(Transition transition, boolean add) {
302 if (transition == null || (add &&
303 (mTransitioningViews == null || mTransitioningViews.isEmpty()))) {
George Mount31a21722014-03-24 17:44:36 -0700304 return null;
305 }
George Mountd4c3c912014-06-09 12:31:34 -0700306 // Add the targets to a set containing transition so that transition
307 // remains unaffected. We don't want to modify the targets of transition itself.
George Mount31a21722014-03-24 17:44:36 -0700308 TransitionSet set = new TransitionSet();
George Mount88815022014-06-25 14:33:54 -0700309 if (mTransitioningViews != null) {
310 for (int i = mTransitioningViews.size() - 1; i >= 0; i--) {
311 View view = mTransitioningViews.get(i);
312 if (add) {
313 set.addTarget(view);
314 } else {
315 set.excludeTarget(view, true);
316 }
George Mount31a21722014-03-24 17:44:36 -0700317 }
318 }
George Mountd4c3c912014-06-09 12:31:34 -0700319 // By adding the transition after addTarget, we prevent addTarget from
320 // affecting transition.
321 set.addTransition(transition);
George Mountfe361d22014-07-08 17:25:25 -0700322
323 if (!add && mTransitioningViews != null && !mTransitioningViews.isEmpty()) {
324 // Allow children of excluded transitioning views, but not the views themselves
325 set = new TransitionSet().addTransition(set);
326 }
327
George Mount31a21722014-03-24 17:44:36 -0700328 return set;
329 }
330
George Mount88815022014-06-25 14:33:54 -0700331 protected Transition configureTransition(Transition transition,
332 boolean includeTransitioningViews) {
George Mount31a21722014-03-24 17:44:36 -0700333 if (transition != null) {
George Mount62ab9b72014-05-02 13:51:17 -0700334 transition = transition.clone();
335 transition.setEpicenterCallback(mEpicenterCallback);
George Mount88815022014-06-25 14:33:54 -0700336 transition = setTargets(transition, includeTransitioningViews);
George Mount31a21722014-03-24 17:44:36 -0700337 }
338 return transition;
339 }
340
George Mount62ab9b72014-05-02 13:51:17 -0700341 protected static Transition mergeTransitions(Transition transition1, Transition transition2) {
342 if (transition1 == null) {
343 return transition2;
344 } else if (transition2 == null) {
345 return transition1;
346 } else {
347 TransitionSet transitionSet = new TransitionSet();
348 transitionSet.addTransition(transition1);
349 transitionSet.addTransition(transition2);
350 return transitionSet;
George Mountcaa03102014-04-15 09:01:32 -0700351 }
George Mountcaa03102014-04-15 09:01:32 -0700352 }
353
George Mount1fecfb22014-06-18 14:55:55 -0700354 protected ArrayMap<String, View> mapSharedElements(ArrayList<String> accepted,
355 ArrayList<View> localViews) {
356 ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
George Mountce725a42014-08-27 16:10:46 -0700357 if (accepted != null) {
358 for (int i = 0; i < accepted.size(); i++) {
359 sharedElements.put(accepted.get(i), localViews.get(i));
George Mount62ab9b72014-05-02 13:51:17 -0700360 }
George Mountce725a42014-08-27 16:10:46 -0700361 } else {
George Mount48bd13c2014-09-12 10:54:54 -0700362 ViewGroup decorView = getDecor();
363 if (decorView != null) {
364 decorView.findNamedViews(sharedElements);
365 }
George Mount1fecfb22014-06-18 14:55:55 -0700366 }
367 return sharedElements;
368 }
369
George Mount62ab9b72014-05-02 13:51:17 -0700370 protected void setResultReceiver(ResultReceiver resultReceiver) {
371 mResultReceiver = resultReceiver;
George Mount080443b2014-05-05 10:47:00 -0700372 }
373
George Mounta712e8c2014-05-20 15:10:20 -0700374 protected abstract Transition getViewsTransition();
George Mount080443b2014-05-05 10:47:00 -0700375
George Mountfe361d22014-07-08 17:25:25 -0700376 private void setSharedElementState(View view, String name, Bundle transitionArgs,
Dake Gu7bf379c2014-07-15 16:29:38 -0700377 Matrix tempMatrix, RectF tempRect, int[] decorLoc) {
George Mountc93ca162014-05-23 19:21:36 -0700378 Bundle sharedElementBundle = transitionArgs.getBundle(name);
379 if (sharedElementBundle == null) {
380 return;
381 }
382
383 if (view instanceof ImageView) {
384 int scaleTypeInt = sharedElementBundle.getInt(KEY_SCALE_TYPE, -1);
385 if (scaleTypeInt >= 0) {
386 ImageView imageView = (ImageView) view;
387 ImageView.ScaleType scaleType = SCALE_TYPE_VALUES[scaleTypeInt];
388 imageView.setScaleType(scaleType);
389 if (scaleType == ImageView.ScaleType.MATRIX) {
390 float[] matrixValues = sharedElementBundle.getFloatArray(KEY_IMAGE_MATRIX);
Dake Gu7bf379c2014-07-15 16:29:38 -0700391 tempMatrix.setValues(matrixValues);
392 imageView.setImageMatrix(tempMatrix);
George Mountc93ca162014-05-23 19:21:36 -0700393 }
394 }
395 }
396
397 float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
398 view.setTranslationZ(z);
George Mount26c82b62014-08-08 15:43:59 -0700399 float elevation = sharedElementBundle.getFloat(KEY_ELEVATION);
400 view.setElevation(elevation);
George Mountc93ca162014-05-23 19:21:36 -0700401
Dake Gu7bf379c2014-07-15 16:29:38 -0700402 float left = sharedElementBundle.getFloat(KEY_SCREEN_LEFT);
403 float top = sharedElementBundle.getFloat(KEY_SCREEN_TOP);
404 float right = sharedElementBundle.getFloat(KEY_SCREEN_RIGHT);
405 float bottom = sharedElementBundle.getFloat(KEY_SCREEN_BOTTOM);
George Mountc93ca162014-05-23 19:21:36 -0700406
Dake Gu7bf379c2014-07-15 16:29:38 -0700407 if (decorLoc != null) {
408 left -= decorLoc[0];
409 top -= decorLoc[1];
George Mount480ca822014-08-08 16:35:48 -0700410 right -= decorLoc[0];
411 bottom -= decorLoc[1];
Dake Gu7bf379c2014-07-15 16:29:38 -0700412 } else {
413 // Find the location in the view's parent
George Mountfe361d22014-07-08 17:25:25 -0700414 getSharedElementParentMatrix(view, tempMatrix);
Dake Gu7bf379c2014-07-15 16:29:38 -0700415 tempRect.set(left, top, right, bottom);
416 tempMatrix.mapRect(tempRect);
417
418 float leftInParent = tempRect.left;
419 float topInParent = tempRect.top;
420
421 // Find the size of the view
422 view.getInverseMatrix().mapRect(tempRect);
423 float width = tempRect.width();
424 float height = tempRect.height();
425
426 // Now determine the offset due to view transform:
427 view.setLeft(0);
428 view.setTop(0);
429 view.setRight(Math.round(width));
430 view.setBottom(Math.round(height));
431 tempRect.set(0, 0, width, height);
432 view.getMatrix().mapRect(tempRect);
433
George Mountfe361d22014-07-08 17:25:25 -0700434 ViewGroup parent = (ViewGroup) view.getParent();
Dake Gu7bf379c2014-07-15 16:29:38 -0700435 left = leftInParent - tempRect.left + parent.getScrollX();
436 top = topInParent - tempRect.top + parent.getScrollY();
437 right = left + width;
438 bottom = top + height;
439 }
440
441 int x = Math.round(left);
442 int y = Math.round(top);
443 int width = Math.round(right) - x;
444 int height = Math.round(bottom) - y;
George Mountc93ca162014-05-23 19:21:36 -0700445 int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
446 int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
447 view.measure(widthSpec, heightSpec);
448
Dake Gu7bf379c2014-07-15 16:29:38 -0700449 view.layout(x, y, x + width, y + height);
George Mountc93ca162014-05-23 19:21:36 -0700450 }
451
George Mountfe361d22014-07-08 17:25:25 -0700452 protected void getSharedElementParentMatrix(View view, Matrix matrix) {
453 // Find the location in the view's parent
454 ViewGroup parent = (ViewGroup) view.getParent();
455 matrix.reset();
456 parent.transformMatrixToLocal(matrix);
457 }
458
Dake Guc18f4cc2014-07-11 17:48:37 -0700459 protected ArrayList<SharedElementOriginalState> setSharedElementState(
George Mountc93ca162014-05-23 19:21:36 -0700460 Bundle sharedElementState, final ArrayList<View> snapshots) {
Dake Guc18f4cc2014-07-11 17:48:37 -0700461 ArrayList<SharedElementOriginalState> originalImageState =
462 new ArrayList<SharedElementOriginalState>();
George Mountc93ca162014-05-23 19:21:36 -0700463 if (sharedElementState != null) {
Dake Gu7bf379c2014-07-15 16:29:38 -0700464 Matrix tempMatrix = new Matrix();
465 RectF tempRect = new RectF();
George Mount1732f522014-09-17 16:59:36 -0700466 final int numSharedElements = mSharedElements.size();
467 for (int i = 0; i < numSharedElements; i++) {
George Mountc93ca162014-05-23 19:21:36 -0700468 View sharedElement = mSharedElements.get(i);
469 String name = mSharedElementNames.get(i);
Dake Guc18f4cc2014-07-11 17:48:37 -0700470 SharedElementOriginalState originalState = getOldSharedElementState(sharedElement,
George Mountc93ca162014-05-23 19:21:36 -0700471 name, sharedElementState);
Dake Guc18f4cc2014-07-11 17:48:37 -0700472 originalImageState.add(originalState);
Dake Gu7bf379c2014-07-15 16:29:38 -0700473 setSharedElementState(sharedElement, name, sharedElementState,
474 tempMatrix, tempRect, null);
George Mountc93ca162014-05-23 19:21:36 -0700475 }
476 }
George Mount1732f522014-09-17 16:59:36 -0700477 if (mListener != null) {
478 mListener.onSharedElementStart(mSharedElementNames, mSharedElements, snapshots);
479 }
George Mountfe361d22014-07-08 17:25:25 -0700480 return originalImageState;
481 }
George Mountc93ca162014-05-23 19:21:36 -0700482
George Mountfe361d22014-07-08 17:25:25 -0700483 protected void notifySharedElementEnd(ArrayList<View> snapshots) {
George Mount1732f522014-09-17 16:59:36 -0700484 if (mListener != null) {
485 mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, snapshots);
486 }
George Mountfe361d22014-07-08 17:25:25 -0700487 }
488
489 protected void scheduleSetSharedElementEnd(final ArrayList<View> snapshots) {
George Mount6e7fb602014-09-04 16:20:20 -0700490 final View decorView = getDecor();
George Mount48bd13c2014-09-12 10:54:54 -0700491 if (decorView != null) {
492 decorView.getViewTreeObserver().addOnPreDrawListener(
493 new ViewTreeObserver.OnPreDrawListener() {
494 @Override
495 public boolean onPreDraw() {
496 decorView.getViewTreeObserver().removeOnPreDrawListener(this);
497 notifySharedElementEnd(snapshots);
498 return true;
499 }
George Mountc93ca162014-05-23 19:21:36 -0700500 }
George Mount48bd13c2014-09-12 10:54:54 -0700501 );
502 }
George Mountc93ca162014-05-23 19:21:36 -0700503 }
504
Dake Guc18f4cc2014-07-11 17:48:37 -0700505 private static SharedElementOriginalState getOldSharedElementState(View view, String name,
George Mountc93ca162014-05-23 19:21:36 -0700506 Bundle transitionArgs) {
Dake Guc18f4cc2014-07-11 17:48:37 -0700507
508 SharedElementOriginalState state = new SharedElementOriginalState();
509 state.mLeft = view.getLeft();
510 state.mTop = view.getTop();
511 state.mRight = view.getRight();
512 state.mBottom = view.getBottom();
513 state.mMeasuredWidth = view.getMeasuredWidth();
514 state.mMeasuredHeight = view.getMeasuredHeight();
George Mount26c82b62014-08-08 15:43:59 -0700515 state.mTranslationZ = view.getTranslationZ();
516 state.mElevation = view.getElevation();
George Mountc93ca162014-05-23 19:21:36 -0700517 if (!(view instanceof ImageView)) {
Dake Guc18f4cc2014-07-11 17:48:37 -0700518 return state;
George Mountc93ca162014-05-23 19:21:36 -0700519 }
520 Bundle bundle = transitionArgs.getBundle(name);
521 if (bundle == null) {
Dake Guc18f4cc2014-07-11 17:48:37 -0700522 return state;
George Mountc93ca162014-05-23 19:21:36 -0700523 }
524 int scaleTypeInt = bundle.getInt(KEY_SCALE_TYPE, -1);
525 if (scaleTypeInt < 0) {
Dake Guc18f4cc2014-07-11 17:48:37 -0700526 return state;
George Mountc93ca162014-05-23 19:21:36 -0700527 }
528
529 ImageView imageView = (ImageView) view;
Dake Guc18f4cc2014-07-11 17:48:37 -0700530 state.mScaleType = imageView.getScaleType();
531 if (state.mScaleType == ImageView.ScaleType.MATRIX) {
532 state.mMatrix = new Matrix(imageView.getImageMatrix());
George Mountc93ca162014-05-23 19:21:36 -0700533 }
Dake Guc18f4cc2014-07-11 17:48:37 -0700534 return state;
George Mountc93ca162014-05-23 19:21:36 -0700535 }
536
537 protected ArrayList<View> createSnapshots(Bundle state, Collection<String> names) {
538 int numSharedElements = names.size();
539 if (numSharedElements == 0) {
540 return null;
541 }
542 ArrayList<View> snapshots = new ArrayList<View>(numSharedElements);
543 Context context = getWindow().getContext();
Dake Gu7bf379c2014-07-15 16:29:38 -0700544 int[] decorLoc = new int[2];
George Mount48bd13c2014-09-12 10:54:54 -0700545 ViewGroup decorView = getDecor();
546 if (decorView != null) {
547 decorView.getLocationOnScreen(decorLoc);
548 }
George Mountc93ca162014-05-23 19:21:36 -0700549 for (String name: names) {
550 Bundle sharedElementBundle = state.getBundle(name);
551 if (sharedElementBundle != null) {
George Mount480ca822014-08-08 16:35:48 -0700552 Parcelable parcelable = sharedElementBundle.getParcelable(KEY_SNAPSHOT);
553 View snapshot = null;
George Mount1732f522014-09-17 16:59:36 -0700554 if (parcelable != null && mListener != null) {
George Mount65580562014-08-29 08:15:48 -0700555 snapshot = mListener.onCreateSnapshotView(context, parcelable);
George Mountc93ca162014-05-23 19:21:36 -0700556 }
George Mount480ca822014-08-08 16:35:48 -0700557 if (snapshot != null) {
558 setSharedElementState(snapshot, name, state, null, null, decorLoc);
559 }
George Mountc93ca162014-05-23 19:21:36 -0700560 snapshots.add(snapshot);
561 }
562 }
563 return snapshots;
564 }
565
Dake Guc18f4cc2014-07-11 17:48:37 -0700566 protected static void setOriginalSharedElementState(ArrayList<View> sharedElements,
567 ArrayList<SharedElementOriginalState> originalState) {
George Mountc93ca162014-05-23 19:21:36 -0700568 for (int i = 0; i < originalState.size(); i++) {
Dake Guc18f4cc2014-07-11 17:48:37 -0700569 View view = sharedElements.get(i);
570 SharedElementOriginalState state = originalState.get(i);
571 if (view instanceof ImageView && state.mScaleType != null) {
572 ImageView imageView = (ImageView) view;
573 imageView.setScaleType(state.mScaleType);
574 if (state.mScaleType == ImageView.ScaleType.MATRIX) {
575 imageView.setImageMatrix(state.mMatrix);
576 }
577 }
George Mount26c82b62014-08-08 15:43:59 -0700578 view.setElevation(state.mElevation);
579 view.setTranslationZ(state.mTranslationZ);
580 int widthSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredWidth,
Dake Guc18f4cc2014-07-11 17:48:37 -0700581 View.MeasureSpec.EXACTLY);
582 int heightSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredHeight,
583 View.MeasureSpec.EXACTLY);
584 view.measure(widthSpec, heightSpec);
585 view.layout(state.mLeft, state.mTop, state.mRight, state.mBottom);
George Mountc93ca162014-05-23 19:21:36 -0700586 }
587 }
588
589 protected Bundle captureSharedElementState() {
590 Bundle bundle = new Bundle();
Dake Gu7bf379c2014-07-15 16:29:38 -0700591 RectF tempBounds = new RectF();
592 Matrix tempMatrix = new Matrix();
Dake Guf03c1392014-07-25 15:36:23 -0700593 for (int i = 0; i < mSharedElements.size(); i++) {
George Mountc93ca162014-05-23 19:21:36 -0700594 View sharedElement = mSharedElements.get(i);
595 String name = mSharedElementNames.get(i);
Dake Gu7bf379c2014-07-15 16:29:38 -0700596 captureSharedElementState(sharedElement, name, bundle, tempMatrix, tempBounds);
George Mountc93ca162014-05-23 19:21:36 -0700597 }
598 return bundle;
599 }
600
George Mounta0a02602014-06-20 18:22:26 -0700601 protected void clearState() {
602 // Clear the state so that we can't hold any references accidentally and leak memory.
603 mWindow = null;
George Mounta0a02602014-06-20 18:22:26 -0700604 mSharedElements.clear();
George Mountb694e082014-09-12 07:34:52 -0700605 mTransitioningViews = null;
George Mount0f0c4732014-09-05 13:47:47 -0700606 mOriginalAlphas.clear();
George Mounta0a02602014-06-20 18:22:26 -0700607 mResultReceiver = null;
608 mPendingTransition = null;
Dake Gufc0fc0e2014-08-01 15:39:11 -0700609 mListener = null;
George Mounta0a02602014-06-20 18:22:26 -0700610 }
611
George Mounted1e01d2014-06-05 13:49:12 -0700612 protected long getFadeDuration() {
613 return getWindow().getTransitionBackgroundFadeDuration();
614 }
615
George Mount0f0c4732014-09-05 13:47:47 -0700616 protected void hideViews(ArrayList<View> views) {
George Mountfe361d22014-07-08 17:25:25 -0700617 int count = views.size();
618 for (int i = 0; i < count; i++) {
George Mount0f0c4732014-09-05 13:47:47 -0700619 View view = views.get(i);
620 if (!mOriginalAlphas.containsKey(view)) {
621 mOriginalAlphas.put(view, view.getAlpha());
622 }
623 view.setAlpha(0f);
George Mount0f0c4732014-09-05 13:47:47 -0700624 }
625 }
626
George Mountce2ee3d2014-09-09 15:04:31 -0700627 protected void showViews(ArrayList<View> views, boolean setTransitionAlpha) {
George Mount0f0c4732014-09-05 13:47:47 -0700628 int count = views.size();
629 for (int i = 0; i < count; i++) {
George Mount653ea662014-09-12 13:56:32 -0700630 showView(views.get(i), setTransitionAlpha);
631 }
632 }
633
634 private void showView(View view, boolean setTransitionAlpha) {
635 Float alpha = mOriginalAlphas.remove(view);
636 if (alpha != null) {
637 view.setAlpha(alpha);
638 }
639 if (setTransitionAlpha) {
640 view.setTransitionAlpha(1f);
George Mountb5ef7f82014-07-09 14:55:03 -0700641 }
642 }
643
George Mountc93ca162014-05-23 19:21:36 -0700644 /**
645 * Captures placement information for Views with a shared element name for
646 * Activity Transitions.
647 *
648 * @param view The View to capture the placement information for.
649 * @param name The shared element name in the target Activity to apply the placement
650 * information for.
651 * @param transitionArgs Bundle to store shared element placement information.
George Mount8e43d6d2014-06-05 17:25:46 -0700652 * @param tempBounds A temporary Rect for capturing the current location of views.
George Mountc93ca162014-05-23 19:21:36 -0700653 */
George Mount480ca822014-08-08 16:35:48 -0700654 protected void captureSharedElementState(View view, String name, Bundle transitionArgs,
Dake Gu7bf379c2014-07-15 16:29:38 -0700655 Matrix tempMatrix, RectF tempBounds) {
George Mountc93ca162014-05-23 19:21:36 -0700656 Bundle sharedElementBundle = new Bundle();
Dake Gu7bf379c2014-07-15 16:29:38 -0700657 tempMatrix.reset();
658 view.transformMatrixToGlobal(tempMatrix);
George Mount8e43d6d2014-06-05 17:25:46 -0700659 tempBounds.set(0, 0, view.getWidth(), view.getHeight());
Dake Gu7bf379c2014-07-15 16:29:38 -0700660 tempMatrix.mapRect(tempBounds);
George Mountc93ca162014-05-23 19:21:36 -0700661
Dake Gu7bf379c2014-07-15 16:29:38 -0700662 sharedElementBundle.putFloat(KEY_SCREEN_LEFT, tempBounds.left);
663 sharedElementBundle.putFloat(KEY_SCREEN_RIGHT, tempBounds.right);
664 sharedElementBundle.putFloat(KEY_SCREEN_TOP, tempBounds.top);
665 sharedElementBundle.putFloat(KEY_SCREEN_BOTTOM, tempBounds.bottom);
George Mountc93ca162014-05-23 19:21:36 -0700666 sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ());
George Mount26c82b62014-08-08 15:43:59 -0700667 sharedElementBundle.putFloat(KEY_ELEVATION, view.getElevation());
George Mountc93ca162014-05-23 19:21:36 -0700668
George Mount1732f522014-09-17 16:59:36 -0700669 Parcelable bitmap = null;
670 if (mListener != null) {
671 bitmap = mListener.onCaptureSharedElementSnapshot(view, tempMatrix, tempBounds);
672 }
673
George Mount480ca822014-08-08 16:35:48 -0700674 if (bitmap != null) {
675 sharedElementBundle.putParcelable(KEY_SNAPSHOT, bitmap);
George Mountc93ca162014-05-23 19:21:36 -0700676 }
677
678 if (view instanceof ImageView) {
679 ImageView imageView = (ImageView) view;
680 int scaleTypeInt = scaleTypeToInt(imageView.getScaleType());
681 sharedElementBundle.putInt(KEY_SCALE_TYPE, scaleTypeInt);
682 if (imageView.getScaleType() == ImageView.ScaleType.MATRIX) {
683 float[] matrix = new float[9];
684 imageView.getImageMatrix().getValues(matrix);
685 sharedElementBundle.putFloatArray(KEY_IMAGE_MATRIX, matrix);
686 }
687 }
688
689 transitionArgs.putBundle(name, sharedElementBundle);
690 }
691
George Mount67d92432014-06-06 13:34:20 -0700692
693 protected void startTransition(Runnable runnable) {
694 if (mIsStartingTransition) {
695 mPendingTransition = runnable;
696 } else {
697 mIsStartingTransition = true;
698 runnable.run();
699 }
700 }
701
George Mount13ccb792014-06-06 17:02:20 -0700702 protected void transitionStarted() {
703 mIsStartingTransition = false;
704 }
705
George Mountfe361d22014-07-08 17:25:25 -0700706 protected void moveSharedElementsToOverlay() {
George Mountb89d5cc2014-08-18 16:50:50 -0700707 if (!mWindow.getSharedElementsUseOverlay()) {
708 return;
709 }
George Mountfe361d22014-07-08 17:25:25 -0700710 int numSharedElements = mSharedElements.size();
711 ViewGroup decor = getDecor();
712 if (decor != null) {
713 boolean moveWithParent = moveSharedElementWithParent();
714 for (int i = 0; i < numSharedElements; i++) {
715 View view = mSharedElements.get(i);
716 GhostView.addGhost(view, decor);
717 ViewGroup parent = (ViewGroup) view.getParent();
718 if (moveWithParent && !isInTransitionGroup(parent, decor)) {
George Mount6e7fb602014-09-04 16:20:20 -0700719 GhostViewListeners listener = new GhostViewListeners(view, parent, decor);
George Mountfe361d22014-07-08 17:25:25 -0700720 parent.getViewTreeObserver().addOnPreDrawListener(listener);
721 mGhostViewListeners.add(listener);
722 }
723 }
724 }
725 }
726
727 protected boolean moveSharedElementWithParent() {
728 return true;
729 }
730
731 public static boolean isInTransitionGroup(ViewParent viewParent, ViewGroup decor) {
732 if (viewParent == decor || !(viewParent instanceof ViewGroup)) {
733 return false;
734 }
735 ViewGroup parent = (ViewGroup) viewParent;
736 if (parent.isTransitionGroup()) {
737 return true;
738 } else {
739 return isInTransitionGroup(parent.getParent(), decor);
740 }
741 }
742
743 protected void moveSharedElementsFromOverlay() {
George Mountb89d5cc2014-08-18 16:50:50 -0700744 int numListeners = mGhostViewListeners.size();
745 for (int i = 0; i < numListeners; i++) {
746 GhostViewListeners listener = mGhostViewListeners.get(i);
747 ViewGroup parent = (ViewGroup) listener.getView().getParent();
748 parent.getViewTreeObserver().removeOnPreDrawListener(listener);
749 }
750 mGhostViewListeners.clear();
751
752 if (mWindow == null || !mWindow.getSharedElementsUseOverlay()) {
753 return;
754 }
George Mountfe361d22014-07-08 17:25:25 -0700755 ViewGroup decor = getDecor();
756 if (decor != null) {
757 ViewGroupOverlay overlay = decor.getOverlay();
758 int count = mSharedElements.size();
759 for (int i = 0; i < count; i++) {
760 View sharedElement = mSharedElements.get(i);
761 GhostView.removeGhost(sharedElement);
762 }
763 }
George Mountfe361d22014-07-08 17:25:25 -0700764 }
765
766 protected void setGhostVisibility(int visibility) {
767 int numSharedElements = mSharedElements.size();
768 for (int i = 0; i < numSharedElements; i++) {
769 GhostView ghostView = GhostView.getGhost(mSharedElements.get(i));
770 if (ghostView != null) {
771 ghostView.setVisibility(visibility);
772 }
773 }
774 }
775
776 protected void scheduleGhostVisibilityChange(final int visibility) {
George Mount6e7fb602014-09-04 16:20:20 -0700777 final View decorView = getDecor();
George Mount48bd13c2014-09-12 10:54:54 -0700778 if (decorView != null) {
779 decorView.getViewTreeObserver()
780 .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
781 @Override
782 public boolean onPreDraw() {
783 decorView.getViewTreeObserver().removeOnPreDrawListener(this);
784 setGhostVisibility(visibility);
785 return true;
786 }
787 });
788 }
George Mountfe361d22014-07-08 17:25:25 -0700789 }
790
George Mount67d92432014-06-06 13:34:20 -0700791 protected class ContinueTransitionListener extends Transition.TransitionListenerAdapter {
792 @Override
793 public void onTransitionStart(Transition transition) {
794 mIsStartingTransition = false;
795 Runnable pending = mPendingTransition;
796 mPendingTransition = null;
797 if (pending != null) {
798 startTransition(pending);
799 }
800 }
801 }
802
George Mountc93ca162014-05-23 19:21:36 -0700803 private static int scaleTypeToInt(ImageView.ScaleType scaleType) {
804 for (int i = 0; i < SCALE_TYPE_VALUES.length; i++) {
805 if (scaleType == SCALE_TYPE_VALUES[i]) {
806 return i;
807 }
808 }
809 return -1;
810 }
811
George Mount31a21722014-03-24 17:44:36 -0700812 private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
813 private Rect mEpicenter;
814
815 public void setEpicenter(Rect epicenter) { mEpicenter = epicenter; }
816
817 @Override
George Mountdc21d3b2014-06-05 09:42:48 -0700818 public Rect onGetEpicenter(Transition transition) {
George Mount31a21722014-03-24 17:44:36 -0700819 return mEpicenter;
820 }
821 }
George Mount800d72b2014-05-19 07:09:00 -0700822
George Mountfe361d22014-07-08 17:25:25 -0700823 private static class GhostViewListeners implements ViewTreeObserver.OnPreDrawListener {
824 private View mView;
825 private ViewGroup mDecor;
George Mount6e7fb602014-09-04 16:20:20 -0700826 private View mParent;
George Mountfe361d22014-07-08 17:25:25 -0700827 private Matrix mMatrix = new Matrix();
828
George Mount6e7fb602014-09-04 16:20:20 -0700829 public GhostViewListeners(View view, View parent, ViewGroup decor) {
George Mountfe361d22014-07-08 17:25:25 -0700830 mView = view;
George Mount6e7fb602014-09-04 16:20:20 -0700831 mParent = parent;
George Mountfe361d22014-07-08 17:25:25 -0700832 mDecor = decor;
833 }
834
835 public View getView() {
836 return mView;
837 }
838
839 @Override
840 public boolean onPreDraw() {
George Mountfe361d22014-07-08 17:25:25 -0700841 GhostView ghostView = GhostView.getGhost(mView);
842 if (ghostView == null) {
George Mount6e7fb602014-09-04 16:20:20 -0700843 mParent.getViewTreeObserver().removeOnPreDrawListener(this);
George Mountfe361d22014-07-08 17:25:25 -0700844 } else {
845 GhostView.calculateMatrix(mView, mDecor, mMatrix);
846 ghostView.setMatrix(mMatrix);
847 }
848 return true;
849 }
850 }
851
Dake Guc18f4cc2014-07-11 17:48:37 -0700852 static class SharedElementOriginalState {
853 int mLeft;
854 int mTop;
855 int mRight;
856 int mBottom;
857 int mMeasuredWidth;
858 int mMeasuredHeight;
859 ImageView.ScaleType mScaleType;
860 Matrix mMatrix;
George Mount26c82b62014-08-08 15:43:59 -0700861 float mTranslationZ;
862 float mElevation;
Dake Guc18f4cc2014-07-11 17:48:37 -0700863 }
George Mount31a21722014-03-24 17:44:36 -0700864}