blob: d54ffa0b23f91f5aff536d54f0eea4ff45bc5a64 [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 Mount62ab9b72014-05-02 13:51:17 -070018import android.animation.Animator;
19import android.animation.AnimatorListenerAdapter;
20import android.animation.ObjectAnimator;
George Mount4dc668c2015-04-09 20:55:59 +000021import android.app.SharedElementCallback.OnSharedElementsReadyListener;
George Mount62ab9b72014-05-02 13:51:17 -070022import android.content.Intent;
Craig Mautner85b764e2014-08-27 13:45:10 -070023import android.graphics.Color;
Dake Gu7bf379c2014-07-15 16:29:38 -070024import android.graphics.Matrix;
25import android.graphics.RectF;
George Mount62ab9b72014-05-02 13:51:17 -070026import android.graphics.drawable.ColorDrawable;
George Mount8cab50a2014-05-15 09:57:17 -070027import android.graphics.drawable.Drawable;
George Mount2c256a02015-07-15 16:30:20 -070028import android.os.Build.VERSION_CODES;
George Mount31a21722014-03-24 17:44:36 -070029import android.os.Bundle;
George Mount62ab9b72014-05-02 13:51:17 -070030import android.os.Handler;
31import android.os.Message;
George Mount4dc668c2015-04-09 20:55:59 +000032import android.os.ResultReceiver;
George Mount31a21722014-03-24 17:44:36 -070033import android.transition.Transition;
George Mount62ab9b72014-05-02 13:51:17 -070034import android.transition.TransitionManager;
George Mount31a21722014-03-24 17:44:36 -070035import android.view.View;
George Mounte678ab62014-06-30 15:28:28 -070036import android.view.ViewGroup;
George Mountc93ca162014-05-23 19:21:36 -070037import android.view.ViewTreeObserver;
George Mount31a21722014-03-24 17:44:36 -070038
39import java.util.ArrayList;
40
41/**
42 * This ActivityTransitionCoordinator is created in ActivityOptions#makeSceneTransitionAnimation
43 * to govern the exit of the Scene and the shared elements when calling an Activity as well as
44 * the reentry of the Scene when coming back from the called Activity.
45 */
46class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
47 private static final String TAG = "ExitTransitionCoordinator";
George Mount8cab50a2014-05-15 09:57:17 -070048 private static final long MAX_WAIT_MS = 1000;
George Mount31a21722014-03-24 17:44:36 -070049
George Mount62ab9b72014-05-02 13:51:17 -070050 private Bundle mSharedElementBundle;
George Mount62ab9b72014-05-02 13:51:17 -070051 private boolean mExitNotified;
George Mount62ab9b72014-05-02 13:51:17 -070052 private boolean mSharedElementNotified;
George Mount62ab9b72014-05-02 13:51:17 -070053 private Activity mActivity;
George Mount62ab9b72014-05-02 13:51:17 -070054 private boolean mIsBackgroundReady;
George Mount62ab9b72014-05-02 13:51:17 -070055 private boolean mIsCanceled;
George Mount62ab9b72014-05-02 13:51:17 -070056 private Handler mHandler;
George Mount8cab50a2014-05-15 09:57:17 -070057 private ObjectAnimator mBackgroundAnimator;
George Mount8cab50a2014-05-15 09:57:17 -070058 private boolean mIsHidden;
George Mountc93ca162014-05-23 19:21:36 -070059 private Bundle mExitSharedElementBundle;
George Mount700db2a2014-07-07 17:17:49 -070060 private boolean mIsExitStarted;
George Mountb5ef7f82014-07-09 14:55:03 -070061 private boolean mSharedElementsHidden;
62
George Mount62ab9b72014-05-02 13:51:17 -070063 public ExitTransitionCoordinator(Activity activity, ArrayList<String> names,
George Mount1fecfb22014-06-18 14:55:55 -070064 ArrayList<String> accepted, ArrayList<View> mapped, boolean isReturning) {
George Mountfe361d22014-07-08 17:25:25 -070065 super(activity.getWindow(), names, getListener(activity, isReturning), isReturning);
George Mount1fecfb22014-06-18 14:55:55 -070066 viewsReady(mapSharedElements(accepted, mapped));
George Mount60625b02014-06-24 07:46:23 -070067 stripOffscreenViews();
George Mounta712e8c2014-05-20 15:10:20 -070068 mIsBackgroundReady = !isReturning;
George Mount62ab9b72014-05-02 13:51:17 -070069 mActivity = activity;
George Mount31a21722014-03-24 17:44:36 -070070 }
71
George Mount65580562014-08-29 08:15:48 -070072 private static SharedElementCallback getListener(Activity activity, boolean isReturning) {
George Mountd80154f2014-05-21 08:40:03 -070073 return isReturning ? activity.mEnterTransitionListener : activity.mExitTransitionListener;
George Mount800d72b2014-05-19 07:09:00 -070074 }
75
George Mount31a21722014-03-24 17:44:36 -070076 @Override
George Mount62ab9b72014-05-02 13:51:17 -070077 protected void onReceiveResult(int resultCode, Bundle resultData) {
78 switch (resultCode) {
79 case MSG_SET_REMOTE_RECEIVER:
George Mountfe361d22014-07-08 17:25:25 -070080 stopCancel();
George Mount62ab9b72014-05-02 13:51:17 -070081 mResultReceiver = resultData.getParcelable(KEY_REMOTE_RECEIVER);
82 if (mIsCanceled) {
83 mResultReceiver.send(MSG_CANCEL, null);
84 mResultReceiver = null;
85 } else {
George Mount62ab9b72014-05-02 13:51:17 -070086 notifyComplete();
87 }
88 break;
89 case MSG_HIDE_SHARED_ELEMENTS:
George Mountfe361d22014-07-08 17:25:25 -070090 stopCancel();
George Mount62ab9b72014-05-02 13:51:17 -070091 if (!mIsCanceled) {
92 hideSharedElements();
93 }
94 break;
95 case MSG_START_EXIT_TRANSITION:
George Mountfe361d22014-07-08 17:25:25 -070096 mHandler.removeMessages(MSG_CANCEL);
George Mount62ab9b72014-05-02 13:51:17 -070097 startExit();
98 break;
George Mountc93ca162014-05-23 19:21:36 -070099 case MSG_SHARED_ELEMENT_DESTINATION:
100 mExitSharedElementBundle = resultData;
George Mount67d92432014-06-06 13:34:20 -0700101 sharedElementExitBack();
George Mountc93ca162014-05-23 19:21:36 -0700102 break;
103 }
104 }
105
George Mountfe361d22014-07-08 17:25:25 -0700106 private void stopCancel() {
107 if (mHandler != null) {
108 mHandler.removeMessages(MSG_CANCEL);
109 }
110 }
111
112 private void delayCancel() {
113 if (mHandler != null) {
114 mHandler.sendEmptyMessageDelayed(MSG_CANCEL, MAX_WAIT_MS);
115 }
116 }
117
George Mount1fecfb22014-06-18 14:55:55 -0700118 public void resetViews() {
George Mountb694e082014-09-12 07:34:52 -0700119 if (mTransitioningViews != null) {
120 showViews(mTransitioningViews, true);
George Mount62976722016-02-04 16:45:53 -0800121 setTransitioningViewsVisiblity(View.VISIBLE, true);
George Mountb694e082014-09-12 07:34:52 -0700122 }
George Mountce2ee3d2014-09-09 15:04:31 -0700123 showViews(mSharedElements, true);
George Mount1fecfb22014-06-18 14:55:55 -0700124 mIsHidden = true;
George Mount48bd13c2014-09-12 10:54:54 -0700125 ViewGroup decorView = getDecor();
126 if (!mIsReturning && decorView != null) {
127 decorView.suppressLayout(false);
Dake Guf7ff2202014-07-25 14:00:17 -0700128 }
George Mountfe361d22014-07-08 17:25:25 -0700129 moveSharedElementsFromOverlay();
George Mount8d3cd2c2014-07-08 11:07:33 -0700130 clearState();
George Mount1fecfb22014-06-18 14:55:55 -0700131 }
132
George Mount67d92432014-06-06 13:34:20 -0700133 private void sharedElementExitBack() {
George Mount48bd13c2014-09-12 10:54:54 -0700134 final ViewGroup decorView = getDecor();
135 if (decorView != null) {
136 decorView.suppressLayout(true);
Dake Guf7ff2202014-07-25 14:00:17 -0700137 }
George Mount48bd13c2014-09-12 10:54:54 -0700138 if (decorView != null && mExitSharedElementBundle != null &&
139 !mExitSharedElementBundle.isEmpty() &&
Dake Gu872efe42014-08-29 15:24:58 -0700140 !mSharedElements.isEmpty() && getSharedElementTransition() != null) {
George Mount67d92432014-06-06 13:34:20 -0700141 startTransition(new Runnable() {
142 public void run() {
George Mount48bd13c2014-09-12 10:54:54 -0700143 startSharedElementExit(decorView);
George Mount67d92432014-06-06 13:34:20 -0700144 }
145 });
George Mount00dde0b2014-07-01 15:27:07 -0700146 } else {
147 sharedElementTransitionComplete();
George Mount31a21722014-03-24 17:44:36 -0700148 }
149 }
150
George Mount48bd13c2014-09-12 10:54:54 -0700151 private void startSharedElementExit(final ViewGroup decorView) {
George Mount67d92432014-06-06 13:34:20 -0700152 Transition transition = getSharedElementExitTransition();
George Mountfe361d22014-07-08 17:25:25 -0700153 transition.addListener(new Transition.TransitionListenerAdapter() {
154 @Override
155 public void onTransitionEnd(Transition transition) {
156 transition.removeListener(this);
George Mount41725de2015-04-09 08:23:05 -0700157 if (isViewsTransitionComplete()) {
George Mountfe361d22014-07-08 17:25:25 -0700158 delayCancel();
159 }
160 }
161 });
George Mount67d92432014-06-06 13:34:20 -0700162 final ArrayList<View> sharedElementSnapshots = createSnapshots(mExitSharedElementBundle,
163 mSharedElementNames);
George Mount6e7fb602014-09-04 16:20:20 -0700164 decorView.getViewTreeObserver()
George Mount67d92432014-06-06 13:34:20 -0700165 .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
166 @Override
167 public boolean onPreDraw() {
George Mount6e7fb602014-09-04 16:20:20 -0700168 decorView.getViewTreeObserver().removeOnPreDrawListener(this);
George Mount67d92432014-06-06 13:34:20 -0700169 setSharedElementState(mExitSharedElementBundle, sharedElementSnapshots);
170 return true;
171 }
172 });
George Mountfe361d22014-07-08 17:25:25 -0700173 setGhostVisibility(View.INVISIBLE);
174 scheduleGhostVisibilityChange(View.INVISIBLE);
George Mount1732f522014-09-17 16:59:36 -0700175 if (mListener != null) {
176 mListener.onSharedElementEnd(mSharedElementNames, mSharedElements,
177 sharedElementSnapshots);
178 }
George Mount48bd13c2014-09-12 10:54:54 -0700179 TransitionManager.beginDelayedTransition(decorView, transition);
George Mountfe361d22014-07-08 17:25:25 -0700180 scheduleGhostVisibilityChange(View.VISIBLE);
181 setGhostVisibility(View.VISIBLE);
George Mount48bd13c2014-09-12 10:54:54 -0700182 decorView.invalidate();
George Mount67d92432014-06-06 13:34:20 -0700183 }
184
George Mount62ab9b72014-05-02 13:51:17 -0700185 private void hideSharedElements() {
George Mountfe361d22014-07-08 17:25:25 -0700186 moveSharedElementsFromOverlay();
George Mount67d92432014-06-06 13:34:20 -0700187 if (!mIsHidden) {
George Mount0f0c4732014-09-05 13:47:47 -0700188 hideViews(mSharedElements);
George Mount67d92432014-06-06 13:34:20 -0700189 }
George Mountb5ef7f82014-07-09 14:55:03 -0700190 mSharedElementsHidden = true;
George Mountc93ca162014-05-23 19:21:36 -0700191 finishIfNecessary();
George Mount62ab9b72014-05-02 13:51:17 -0700192 }
193
George Mount31a21722014-03-24 17:44:36 -0700194 public void startExit() {
George Mount700db2a2014-07-07 17:17:49 -0700195 if (!mIsExitStarted) {
196 mIsExitStarted = true;
George Mount80141d12015-07-14 10:03:06 -0700197 pauseInput();
George Mount48bd13c2014-09-12 10:54:54 -0700198 ViewGroup decorView = getDecor();
199 if (decorView != null) {
200 decorView.suppressLayout(true);
Dake Guf7ff2202014-07-25 14:00:17 -0700201 }
George Mountfe361d22014-07-08 17:25:25 -0700202 moveSharedElementsToOverlay();
George Mount700db2a2014-07-07 17:17:49 -0700203 startTransition(new Runnable() {
204 @Override
205 public void run() {
206 beginTransitions();
207 }
208 });
George Mount700db2a2014-07-07 17:17:49 -0700209 }
George Mount62ab9b72014-05-02 13:51:17 -0700210 }
211
212 public void startExit(int resultCode, Intent data) {
George Mount700db2a2014-07-07 17:17:49 -0700213 if (!mIsExitStarted) {
214 mIsExitStarted = true;
George Mount80141d12015-07-14 10:03:06 -0700215 pauseInput();
George Mount48bd13c2014-09-12 10:54:54 -0700216 ViewGroup decorView = getDecor();
217 if (decorView != null) {
218 decorView.suppressLayout(true);
Dake Guf7ff2202014-07-25 14:00:17 -0700219 }
George Mount700db2a2014-07-07 17:17:49 -0700220 mHandler = new Handler() {
221 @Override
222 public void handleMessage(Message msg) {
223 mIsCanceled = true;
224 finish();
George Mount62ab9b72014-05-02 13:51:17 -0700225 }
George Mount700db2a2014-07-07 17:17:49 -0700226 };
George Mountfe361d22014-07-08 17:25:25 -0700227 delayCancel();
228 moveSharedElementsToOverlay();
George Mount48bd13c2014-09-12 10:54:54 -0700229 if (decorView != null && decorView.getBackground() == null) {
Craig Mautner85b764e2014-08-27 13:45:10 -0700230 getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLACK));
George Mount62ab9b72014-05-02 13:51:17 -0700231 }
George Mount2c256a02015-07-15 16:30:20 -0700232 final boolean targetsM = decorView == null || decorView.getContext()
Dianne Hackborn0e3de6c2015-07-29 15:20:21 -0700233 .getApplicationInfo().targetSdkVersion >= VERSION_CODES.M;
George Mount2c256a02015-07-15 16:30:20 -0700234 ArrayList<String> sharedElementNames = targetsM ? mSharedElementNames :
235 mAllSharedElementNames;
George Mount700db2a2014-07-07 17:17:49 -0700236 ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(mActivity, this,
George Mount2c256a02015-07-15 16:30:20 -0700237 sharedElementNames, resultCode, data);
George Mount700db2a2014-07-07 17:17:49 -0700238 mActivity.convertToTranslucent(new Activity.TranslucentConversionListener() {
239 @Override
240 public void onTranslucentConversionComplete(boolean drawComplete) {
241 if (!mIsCanceled) {
242 fadeOutBackground();
243 }
244 }
245 }, options);
246 startTransition(new Runnable() {
247 @Override
248 public void run() {
249 startExitTransition();
250 }
251 });
252 }
George Mount67d92432014-06-06 13:34:20 -0700253 }
254
George Mountf1abef62014-09-22 13:58:21 -0700255 public void stop() {
256 if (mIsReturning && mActivity != null) {
257 // Override the previous ActivityOptions. We don't want the
258 // activity to have options since we're essentially canceling the
259 // transition and finishing right now.
260 mActivity.convertToTranslucent(null, null);
261 finish();
262 }
263 }
264
George Mount67d92432014-06-06 13:34:20 -0700265 private void startExitTransition() {
George Mountf451d8a2014-06-23 11:09:32 -0700266 Transition transition = getExitTransition();
George Mount48bd13c2014-09-12 10:54:54 -0700267 ViewGroup decorView = getDecor();
George Mountb694e082014-09-12 07:34:52 -0700268 if (transition != null && decorView != null && mTransitioningViews != null) {
George Mount62976722016-02-04 16:45:53 -0800269 setTransitioningViewsVisiblity(View.VISIBLE, false);
George Mount48bd13c2014-09-12 10:54:54 -0700270 TransitionManager.beginDelayedTransition(decorView, transition);
George Mount62976722016-02-04 16:45:53 -0800271 setTransitioningViewsVisiblity(View.INVISIBLE, true);
George Mountb4c5d7b2014-07-24 13:19:51 -0700272 } else {
273 transitionStarted();
George Mountc93ca162014-05-23 19:21:36 -0700274 }
George Mount62ab9b72014-05-02 13:51:17 -0700275 }
276
277 private void fadeOutBackground() {
George Mount8cab50a2014-05-15 09:57:17 -0700278 if (mBackgroundAnimator == null) {
George Mount700db2a2014-07-07 17:17:49 -0700279 ViewGroup decor = getDecor();
280 Drawable background;
281 if (decor != null && (background = decor.getBackground()) != null) {
George Mount99c82fd2014-09-03 07:27:47 -0700282 background = background.mutate();
283 getWindow().setBackgroundDrawable(background);
George Mount700db2a2014-07-07 17:17:49 -0700284 mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 0);
285 mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
286 @Override
287 public void onAnimationEnd(Animator animation) {
288 mBackgroundAnimator = null;
289 if (!mIsCanceled) {
290 mIsBackgroundReady = true;
291 notifyComplete();
292 }
George Mount8cab50a2014-05-15 09:57:17 -0700293 }
George Mount700db2a2014-07-07 17:17:49 -0700294 });
295 mBackgroundAnimator.setDuration(getFadeDuration());
296 mBackgroundAnimator.start();
George Mountb5ef7f82014-07-09 14:55:03 -0700297 } else {
298 mIsBackgroundReady = true;
George Mount700db2a2014-07-07 17:17:49 -0700299 }
George Mount8cab50a2014-05-15 09:57:17 -0700300 }
George Mount62ab9b72014-05-02 13:51:17 -0700301 }
302
George Mountc93ca162014-05-23 19:21:36 -0700303 private Transition getExitTransition() {
304 Transition viewsTransition = null;
George Mountb694e082014-09-12 07:34:52 -0700305 if (mTransitioningViews != null && !mTransitioningViews.isEmpty()) {
George Mount88815022014-06-25 14:33:54 -0700306 viewsTransition = configureTransition(getViewsTransition(), true);
George Mount62ab9b72014-05-02 13:51:17 -0700307 }
George Mountc93ca162014-05-23 19:21:36 -0700308 if (viewsTransition == null) {
George Mount41725de2015-04-09 08:23:05 -0700309 viewsTransitionComplete();
George Mount62ab9b72014-05-02 13:51:17 -0700310 } else {
George Mountb694e082014-09-12 07:34:52 -0700311 final ArrayList<View> transitioningViews = mTransitioningViews;
George Mount67d92432014-06-06 13:34:20 -0700312 viewsTransition.addListener(new ContinueTransitionListener() {
George Mount62ab9b72014-05-02 13:51:17 -0700313 @Override
314 public void onTransitionEnd(Transition transition) {
George Mounta0a02602014-06-20 18:22:26 -0700315 transition.removeListener(this);
George Mount41725de2015-04-09 08:23:05 -0700316 viewsTransitionComplete();
George Mountb694e082014-09-12 07:34:52 -0700317 if (mIsHidden && transitioningViews != null) {
318 showViews(transitioningViews, true);
George Mount62976722016-02-04 16:45:53 -0800319 setTransitioningViewsVisiblity(View.VISIBLE, true);
George Mount8cab50a2014-05-15 09:57:17 -0700320 }
George Mountfe361d22014-07-08 17:25:25 -0700321 if (mSharedElementBundle != null) {
322 delayCancel();
323 }
324 super.onTransitionEnd(transition);
George Mountc93ca162014-05-23 19:21:36 -0700325 }
George Mount62ab9b72014-05-02 13:51:17 -0700326 });
327 }
George Mountc93ca162014-05-23 19:21:36 -0700328 return viewsTransition;
329 }
330
331 private Transition getSharedElementExitTransition() {
332 Transition sharedElementTransition = null;
333 if (!mSharedElements.isEmpty()) {
George Mount88815022014-06-25 14:33:54 -0700334 sharedElementTransition = configureTransition(getSharedElementTransition(), false);
George Mountc93ca162014-05-23 19:21:36 -0700335 }
336 if (sharedElementTransition == null) {
337 sharedElementTransitionComplete();
338 } else {
George Mount67d92432014-06-06 13:34:20 -0700339 sharedElementTransition.addListener(new ContinueTransitionListener() {
George Mountc93ca162014-05-23 19:21:36 -0700340 @Override
341 public void onTransitionEnd(Transition transition) {
George Mounta0a02602014-06-20 18:22:26 -0700342 transition.removeListener(this);
George Mountc93ca162014-05-23 19:21:36 -0700343 sharedElementTransitionComplete();
344 if (mIsHidden) {
George Mountce2ee3d2014-09-09 15:04:31 -0700345 showViews(mSharedElements, true);
George Mountc93ca162014-05-23 19:21:36 -0700346 }
347 }
348 });
349 mSharedElements.get(0).invalidate();
350 }
351 return sharedElementTransition;
352 }
353
354 private void beginTransitions() {
355 Transition sharedElementTransition = getSharedElementExitTransition();
356 Transition viewsTransition = getExitTransition();
George Mount62ab9b72014-05-02 13:51:17 -0700357
358 Transition transition = mergeTransitions(sharedElementTransition, viewsTransition);
George Mount48bd13c2014-09-12 10:54:54 -0700359 ViewGroup decorView = getDecor();
360 if (transition != null && decorView != null) {
George Mountfe361d22014-07-08 17:25:25 -0700361 setGhostVisibility(View.INVISIBLE);
362 scheduleGhostVisibilityChange(View.INVISIBLE);
George Mount62976722016-02-04 16:45:53 -0800363 if (viewsTransition != null) {
364 setTransitioningViewsVisiblity(View.VISIBLE, false);
365 }
George Mount48bd13c2014-09-12 10:54:54 -0700366 TransitionManager.beginDelayedTransition(decorView, transition);
George Mountfe361d22014-07-08 17:25:25 -0700367 scheduleGhostVisibilityChange(View.VISIBLE);
368 setGhostVisibility(View.VISIBLE);
George Mount62976722016-02-04 16:45:53 -0800369 if (viewsTransition != null) {
370 setTransitioningViewsVisiblity(View.INVISIBLE, true);
371 }
George Mount48bd13c2014-09-12 10:54:54 -0700372 decorView.invalidate();
George Mountb4c5d7b2014-07-24 13:19:51 -0700373 } else {
374 transitionStarted();
George Mounta712e8c2014-05-20 15:10:20 -0700375 }
George Mount62ab9b72014-05-02 13:51:17 -0700376 }
377
George Mount62ab9b72014-05-02 13:51:17 -0700378 protected boolean isReadyToNotify() {
George Mount67d92432014-06-06 13:34:20 -0700379 return mSharedElementBundle != null && mResultReceiver != null && mIsBackgroundReady;
George Mount62ab9b72014-05-02 13:51:17 -0700380 }
381
George Mount41725de2015-04-09 08:23:05 -0700382 @Override
383 protected void sharedElementTransitionComplete() {
George Mount67d92432014-06-06 13:34:20 -0700384 mSharedElementBundle = mExitSharedElementBundle == null
385 ? captureSharedElementState() : captureExitSharedElementsState();
George Mount41725de2015-04-09 08:23:05 -0700386 super.sharedElementTransitionComplete();
George Mount62ab9b72014-05-02 13:51:17 -0700387 }
388
George Mount67d92432014-06-06 13:34:20 -0700389 private Bundle captureExitSharedElementsState() {
390 Bundle bundle = new Bundle();
Dake Gu7bf379c2014-07-15 16:29:38 -0700391 RectF bounds = new RectF();
392 Matrix matrix = new Matrix();
George Mount01e9a972014-07-09 15:39:23 -0700393 for (int i = 0; i < mSharedElements.size(); i++) {
George Mount67d92432014-06-06 13:34:20 -0700394 String name = mSharedElementNames.get(i);
395 Bundle sharedElementState = mExitSharedElementBundle.getBundle(name);
396 if (sharedElementState != null) {
397 bundle.putBundle(name, sharedElementState);
398 } else {
399 View view = mSharedElements.get(i);
Dake Gu7bf379c2014-07-15 16:29:38 -0700400 captureSharedElementState(view, name, bundle, matrix, bounds);
George Mount67d92432014-06-06 13:34:20 -0700401 }
402 }
403 return bundle;
404 }
405
George Mount41725de2015-04-09 08:23:05 -0700406 @Override
407 protected void onTransitionsComplete() {
408 notifyComplete();
409 }
410
George Mount62ab9b72014-05-02 13:51:17 -0700411 protected void notifyComplete() {
412 if (isReadyToNotify()) {
413 if (!mSharedElementNotified) {
414 mSharedElementNotified = true;
George Mountfe361d22014-07-08 17:25:25 -0700415 delayCancel();
George Mount4dc668c2015-04-09 20:55:59 +0000416 if (mListener == null) {
417 mResultReceiver.send(MSG_TAKE_SHARED_ELEMENTS, mSharedElementBundle);
418 notifyExitComplete();
419 } else {
420 final ResultReceiver resultReceiver = mResultReceiver;
421 final Bundle sharedElementBundle = mSharedElementBundle;
422 mListener.onSharedElementsArrived(mSharedElementNames, mSharedElements,
423 new OnSharedElementsReadyListener() {
424 @Override
425 public void onSharedElementsReady() {
426 resultReceiver.send(MSG_TAKE_SHARED_ELEMENTS,
427 sharedElementBundle);
428 notifyExitComplete();
429 }
430 });
Dake Guf7ff2202014-07-25 14:00:17 -0700431 }
George Mount4dc668c2015-04-09 20:55:59 +0000432 } else {
433 notifyExitComplete();
George Mount62ab9b72014-05-02 13:51:17 -0700434 }
435 }
436 }
437
George Mount4dc668c2015-04-09 20:55:59 +0000438 private void notifyExitComplete() {
George Mount41725de2015-04-09 08:23:05 -0700439 if (!mExitNotified && isViewsTransitionComplete()) {
George Mount4dc668c2015-04-09 20:55:59 +0000440 mExitNotified = true;
441 mResultReceiver.send(MSG_EXIT_TRANSITION_COMPLETE, null);
442 mResultReceiver = null; // done talking
443 ViewGroup decorView = getDecor();
444 if (!mIsReturning && decorView != null) {
445 decorView.suppressLayout(false);
446 }
447 finishIfNecessary();
448 }
449 }
450
George Mountc93ca162014-05-23 19:21:36 -0700451 private void finishIfNecessary() {
George Mounte678ab62014-06-30 15:28:28 -0700452 if (mIsReturning && mExitNotified && mActivity != null && (mSharedElements.isEmpty() ||
George Mountb5ef7f82014-07-09 14:55:03 -0700453 mSharedElementsHidden)) {
George Mounta0a02602014-06-20 18:22:26 -0700454 finish();
George Mountc93ca162014-05-23 19:21:36 -0700455 }
456 if (!mIsReturning && mExitNotified) {
457 mActivity = null; // don't need it anymore
458 }
459 }
460
George Mounta0a02602014-06-20 18:22:26 -0700461 private void finish() {
George Mountfe361d22014-07-08 17:25:25 -0700462 stopCancel();
George Mountf1abef62014-09-22 13:58:21 -0700463 if (mActivity != null) {
464 mActivity.mActivityTransitionState.clear();
465 mActivity.finish();
466 mActivity.overridePendingTransition(0, 0);
467 mActivity = null;
468 }
George Mounta0a02602014-06-20 18:22:26 -0700469 // Clear the state so that we can't hold any references accidentally and leak memory.
George Mount3bbc2ed2015-11-18 11:10:55 -0800470 clearState();
471 }
472
473 @Override
474 protected void clearState() {
George Mounta0a02602014-06-20 18:22:26 -0700475 mHandler = null;
George Mounta0a02602014-06-20 18:22:26 -0700476 mSharedElementBundle = null;
477 if (mBackgroundAnimator != null) {
478 mBackgroundAnimator.cancel();
479 mBackgroundAnimator = null;
480 }
481 mExitSharedElementBundle = null;
George Mount3bbc2ed2015-11-18 11:10:55 -0800482 super.clearState();
George Mounta0a02602014-06-20 18:22:26 -0700483 }
484
George Mounta712e8c2014-05-20 15:10:20 -0700485 @Override
George Mountfe361d22014-07-08 17:25:25 -0700486 protected boolean moveSharedElementWithParent() {
487 return !mIsReturning;
488 }
489
490 @Override
George Mounta712e8c2014-05-20 15:10:20 -0700491 protected Transition getViewsTransition() {
492 if (mIsReturning) {
George Mount68f96d82014-07-31 13:13:10 -0700493 return getWindow().getReturnTransition();
George Mounta712e8c2014-05-20 15:10:20 -0700494 } else {
495 return getWindow().getExitTransition();
496 }
497 }
498
499 protected Transition getSharedElementTransition() {
500 if (mIsReturning) {
George Mount68f96d82014-07-31 13:13:10 -0700501 return getWindow().getSharedElementReturnTransition();
George Mounta712e8c2014-05-20 15:10:20 -0700502 } else {
503 return getWindow().getSharedElementExitTransition();
504 }
505 }
George Mount31a21722014-03-24 17:44:36 -0700506}