/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; import android.os.Bundle; import android.os.ResultReceiver; import android.util.ArrayMap; import android.view.View; import android.view.Window; import java.util.ArrayList; /** * This class contains all persistence-related functionality for Activity Transitions. * Activities start exit and enter Activity Transitions through this class. */ class ActivityTransitionState { private static final String ENTERING_SHARED_ELEMENTS = "android:enteringSharedElements"; private static final String ENTERING_MAPPED_FROM = "android:enteringMappedFrom"; private static final String ENTERING_MAPPED_TO = "android:enteringMappedTo"; private static final String EXITING_MAPPED_FROM = "android:exitingMappedFrom"; private static final String EXITING_MAPPED_TO = "android:exitingMappedTo"; /** * The shared elements that the calling Activity has said that they transferred to this * Activity. */ private ArrayList mEnteringNames; /** * The shared elements that this Activity as accepted and mapped to local Views. */ private ArrayList mEnteringFrom; /** * The names of local Views that are mapped to those elements in mEnteringFrom. */ private ArrayList mEnteringTo; /** * The names of shared elements that were shared to the called Activity. */ private ArrayList mExitingFrom; /** * The names of local Views that were shared out, mapped to those elements in mExitingFrom. */ private ArrayList mExitingTo; /** * The ActivityOptions used to call an Activity. Used to make the elements restore * Visibility of exited Views. */ private ActivityOptions mCalledActivityOptions; /** * We must be able to cancel entering transitions to stop changing the Window to * opaque when we exit before making the Window opaque. */ private EnterTransitionCoordinator mEnterTransitionCoordinator; /** * ActivityOptions used on entering this Activity. */ private ActivityOptions mEnterActivityOptions; /** * Has an exit transition been started? If so, we don't want to double-exit. */ private boolean mHasExited; /** * Postpone painting and starting the enter transition until this is false. */ private boolean mIsEnterPostponed; public ActivityTransitionState() { } public void readState(Bundle bundle) { if (bundle != null) { if (mEnterTransitionCoordinator == null || mEnterTransitionCoordinator.isReturning()) { mEnteringNames = bundle.getStringArrayList(ENTERING_SHARED_ELEMENTS); mEnteringFrom = bundle.getStringArrayList(ENTERING_MAPPED_FROM); mEnteringTo = bundle.getStringArrayList(ENTERING_MAPPED_TO); } if (mEnterTransitionCoordinator == null) { mExitingFrom = bundle.getStringArrayList(EXITING_MAPPED_FROM); mExitingTo = bundle.getStringArrayList(EXITING_MAPPED_TO); } } } public void saveState(Bundle bundle) { if (mEnteringNames != null) { bundle.putStringArrayList(ENTERING_SHARED_ELEMENTS, mEnteringNames); bundle.putStringArrayList(ENTERING_MAPPED_FROM, mEnteringFrom); bundle.putStringArrayList(ENTERING_MAPPED_TO, mEnteringTo); } if (mExitingFrom != null) { bundle.putStringArrayList(EXITING_MAPPED_FROM, mExitingFrom); bundle.putStringArrayList(EXITING_MAPPED_TO, mExitingTo); } } public void setEnterActivityOptions(Activity activity, ActivityOptions options) { if (activity.getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS) && options != null && mEnterActivityOptions == null && options.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) { mEnterActivityOptions = options; if (mEnterActivityOptions.isReturning()) { int result = mEnterActivityOptions.getResultCode(); if (result != 0) { activity.onActivityReenter(result, mEnterActivityOptions.getResultData()); } } } } public void enterReady(Activity activity) { if (mEnterActivityOptions == null) { return; } mHasExited = false; ArrayList sharedElementNames = mEnterActivityOptions.getSharedElementNames(); ResultReceiver resultReceiver = mEnterActivityOptions.getResultReceiver(); if (mEnterActivityOptions.isReturning()) { restoreExitedViews(); activity.getWindow().getDecorView().setVisibility(View.VISIBLE); } mEnterTransitionCoordinator = new EnterTransitionCoordinator(activity, resultReceiver, sharedElementNames, mEnterActivityOptions.isReturning()); if (!mIsEnterPostponed) { startEnter(); } } public void postponeEnterTransition() { mIsEnterPostponed = true; } public void startPostponedEnterTransition() { if (mIsEnterPostponed) { mIsEnterPostponed = false; if (mEnterTransitionCoordinator != null) { startEnter(); } } } private void startEnter() { if (mEnterActivityOptions.isReturning()) { mEnterTransitionCoordinator.viewsReady(mExitingFrom, mExitingTo); } else { mEnterTransitionCoordinator.viewsReady(null, null); mEnteringNames = mEnterTransitionCoordinator.getAllSharedElementNames(); mEnteringFrom = mEnterTransitionCoordinator.getAcceptedNames(); mEnteringTo = mEnterTransitionCoordinator.getMappedNames(); } mExitingFrom = null; mExitingTo = null; mEnterActivityOptions = null; } public void onStop() { restoreExitedViews(); if (mEnterTransitionCoordinator != null) { mEnterTransitionCoordinator.stop(); mEnterTransitionCoordinator = null; } } public void onResume() { restoreExitedViews(); } private void restoreExitedViews() { if (mCalledActivityOptions != null) { mCalledActivityOptions.dispatchActivityStopped(); mCalledActivityOptions = null; } } public boolean startExitBackTransition(Activity activity) { if (mEnteringNames == null) { return false; } else { if (!mHasExited) { mHasExited = true; if (mEnterTransitionCoordinator != null) { mEnterTransitionCoordinator.stop(); mEnterTransitionCoordinator = null; } ArrayMap sharedElements = new ArrayMap(); activity.getWindow().getDecorView().findNamedViews(sharedElements); ExitTransitionCoordinator exitCoordinator = new ExitTransitionCoordinator(activity, mEnteringNames, mEnteringFrom, mEnteringTo, true); exitCoordinator.startExit(activity.mResultCode, activity.mResultData); } return true; } } public void startExitOutTransition(Activity activity, Bundle options) { if (!activity.getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) { return; } mCalledActivityOptions = new ActivityOptions(options); if (mCalledActivityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) { mExitingFrom = mCalledActivityOptions.getSharedElementNames(); mExitingTo = mCalledActivityOptions.getLocalSharedElementNames(); mCalledActivityOptions.dispatchStartExit(); } } }