ActivityTransitionState.java revision 8cab50afda0d8485436f72a93d668697f549d3b3
1/*
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
18import android.os.Bundle;
19import android.os.ResultReceiver;
20import android.util.ArrayMap;
21import android.view.View;
22import android.view.Window;
23
24import java.util.ArrayList;
25
26/**
27 * This class contains all persistence-related functionality for Activity Transitions.
28 * Activities start exit and enter Activity Transitions through this class.
29 */
30class ActivityTransitionState {
31
32    private static final String ENTERING_SHARED_ELEMENTS = "android:enteringSharedElements";
33
34    private static final String ENTERING_MAPPED_FROM = "android:enteringMappedFrom";
35
36    private static final String ENTERING_MAPPED_TO = "android:enteringMappedTo";
37
38    private static final String EXITING_MAPPED_FROM = "android:exitingMappedFrom";
39
40    private static final String EXITING_MAPPED_TO = "android:exitingMappedTo";
41
42    /**
43     * The shared elements that the calling Activity has said that they transferred to this
44     * Activity.
45     */
46    private ArrayList<String> mEnteringNames;
47
48    /**
49     * The shared elements that this Activity as accepted and mapped to local Views.
50     */
51    private ArrayList<String> mEnteringFrom;
52
53    /**
54     * The names of local Views that are mapped to those elements in mEnteringFrom.
55     */
56    private ArrayList<String> mEnteringTo;
57
58    /**
59     * The names of shared elements that were shared to the called Activity.
60     */
61    private ArrayList<String> mExitingFrom;
62
63    /**
64     * The names of local Views that were shared out, mapped to those elements in mExitingFrom.
65     */
66    private ArrayList<String> mExitingTo;
67
68    /**
69     * The ActivityOptions used to call an Activity. Used to make the elements restore
70     * Visibility of exited Views.
71     */
72    private ActivityOptions mCalledActivityOptions;
73
74    /**
75     * We must be able to cancel entering transitions to stop changing the Window to
76     * opaque when we exit before making the Window opaque.
77     */
78    private EnterTransitionCoordinator mEnterTransitionCoordinator;
79
80    /**
81     * ActivityOptions used on entering this Activity.
82     */
83    private ActivityOptions mEnterActivityOptions;
84
85    /**
86     * Has an exit transition been started? If so, we don't want to double-exit.
87     */
88    private boolean mHasExited;
89
90    public ActivityTransitionState() {
91    }
92
93    public void readState(Bundle bundle) {
94        if (bundle != null) {
95            if (mEnterTransitionCoordinator == null || mEnterTransitionCoordinator.isReturning()) {
96                mEnteringNames = bundle.getStringArrayList(ENTERING_SHARED_ELEMENTS);
97                mEnteringFrom = bundle.getStringArrayList(ENTERING_MAPPED_FROM);
98                mEnteringTo = bundle.getStringArrayList(ENTERING_MAPPED_TO);
99            }
100            if (mEnterTransitionCoordinator == null) {
101                mExitingFrom = bundle.getStringArrayList(EXITING_MAPPED_FROM);
102                mExitingTo = bundle.getStringArrayList(EXITING_MAPPED_TO);
103            }
104        }
105    }
106
107    public void saveState(Bundle bundle) {
108        if (mEnteringNames != null) {
109            bundle.putStringArrayList(ENTERING_SHARED_ELEMENTS, mEnteringNames);
110            bundle.putStringArrayList(ENTERING_MAPPED_FROM, mEnteringFrom);
111            bundle.putStringArrayList(ENTERING_MAPPED_TO, mEnteringTo);
112        }
113        if (mExitingFrom != null) {
114            bundle.putStringArrayList(EXITING_MAPPED_FROM, mExitingFrom);
115            bundle.putStringArrayList(EXITING_MAPPED_TO, mExitingTo);
116        }
117    }
118
119    public void setEnterActivityOptions(Activity activity, ActivityOptions options) {
120        if (activity.getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)
121                && options != null && mEnterActivityOptions == null
122                && options.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
123            mEnterActivityOptions = options;
124            if (mEnterActivityOptions.isReturning()) {
125                int result = mEnterActivityOptions.getResultCode();
126                if (result != 0) {
127                    activity.onActivityReenter(result, mEnterActivityOptions.getResultData());
128                }
129            }
130        }
131    }
132
133    public void enterReady(Activity activity) {
134        if (mEnterActivityOptions == null) {
135            return;
136        }
137        mHasExited = false;
138        ArrayList<String> sharedElementNames = mEnterActivityOptions.getSharedElementNames();
139        ResultReceiver resultReceiver = mEnterActivityOptions.getResultReceiver();
140        if (mEnterActivityOptions.isReturning()) {
141            restoreExitedViews();
142            activity.getWindow().getDecorView().setVisibility(View.VISIBLE);
143            mEnterTransitionCoordinator = new EnterTransitionCoordinator(activity,
144                    resultReceiver, sharedElementNames, mExitingFrom, mExitingTo);
145        } else {
146            mEnterTransitionCoordinator = new EnterTransitionCoordinator(activity,
147                    resultReceiver, sharedElementNames, null, null);
148            mEnteringNames = sharedElementNames;
149            mEnteringFrom = mEnterTransitionCoordinator.getAcceptedNames();
150            mEnteringTo = mEnterTransitionCoordinator.getMappedNames();
151        }
152        mExitingFrom = null;
153        mExitingTo = null;
154        mEnterActivityOptions = null;
155    }
156
157    public void onStop() {
158        restoreExitedViews();
159        if (mEnterTransitionCoordinator != null) {
160            mEnterTransitionCoordinator.stop();
161            mEnterTransitionCoordinator = null;
162        }
163    }
164
165    public void onResume() {
166        restoreExitedViews();
167    }
168
169    private void restoreExitedViews() {
170        if (mCalledActivityOptions != null) {
171            mCalledActivityOptions.dispatchActivityStopped();
172            mCalledActivityOptions = null;
173        }
174    }
175
176    public boolean startExitBackTransition(Activity activity) {
177        if (mEnteringNames == null) {
178            return false;
179        } else {
180            if (!mHasExited) {
181                mHasExited = true;
182                if (mEnterTransitionCoordinator != null) {
183                    mEnterTransitionCoordinator.stop();
184                    mEnterTransitionCoordinator = null;
185                }
186                ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
187                activity.getWindow().getDecorView().findNamedViews(sharedElements);
188
189                ExitTransitionCoordinator exitCoordinator =
190                        new ExitTransitionCoordinator(activity, mEnteringNames, mEnteringFrom,
191                                mEnteringTo, true);
192                exitCoordinator.startExit(activity.mResultCode, activity.mResultData);
193            }
194            return true;
195        }
196    }
197
198    public void startExitOutTransition(Activity activity, Bundle options) {
199        if (!activity.getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
200            return;
201        }
202        mCalledActivityOptions = new ActivityOptions(options);
203        if (mCalledActivityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
204            mExitingFrom = mCalledActivityOptions.getSharedElementNames();
205            mExitingTo = mCalledActivityOptions.getLocalSharedElementNames();
206            mCalledActivityOptions.dispatchStartExit();
207        }
208    }
209}
210