am 99d2ffa1: Merge "Split Activity Transitions out of PhoneWindow."
* commit '99d2ffa1268da1258390fa6f272bf41687084d7b': Split Activity Transitions out of PhoneWindow.
This commit is contained in:
@@ -948,10 +948,6 @@ public abstract class ActionBar {
|
||||
public void dispatchMenuVisibilityChanged(boolean visible) {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void captureSharedElements(Map<String, View> sharedElements) {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public ActionMode startActionMode(ActionMode.Callback callback) {
|
||||
return null;
|
||||
|
||||
@@ -18,7 +18,6 @@ package android.app;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.transition.Scene;
|
||||
import android.transition.Transition;
|
||||
import android.transition.TransitionManager;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.SuperNotCalledException;
|
||||
@@ -773,6 +772,8 @@ public class Activity extends ContextThemeWrapper
|
||||
|
||||
private Thread mUiThread;
|
||||
final Handler mHandler = new Handler();
|
||||
private ActivityOptions mCalledActivityOptions;
|
||||
private EnterTransitionCoordinator mEnterTransitionCoordinator;
|
||||
|
||||
/** Return the intent that started this activity. */
|
||||
public Intent getIntent() {
|
||||
@@ -1026,6 +1027,9 @@ public class Activity extends ContextThemeWrapper
|
||||
mTitleReady = true;
|
||||
onTitleChanged(getTitle(), getTitleColor());
|
||||
}
|
||||
if (mEnterTransitionCoordinator != null) {
|
||||
mEnterTransitionCoordinator.readyToEnter();
|
||||
}
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
@@ -1106,6 +1110,7 @@ public class Activity extends ContextThemeWrapper
|
||||
protected void onResume() {
|
||||
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onResume " + this);
|
||||
getApplication().dispatchActivityResumed(this);
|
||||
mCalledActivityOptions = null;
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
@@ -1398,8 +1403,9 @@ public class Activity extends ContextThemeWrapper
|
||||
protected void onStop() {
|
||||
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStop " + this);
|
||||
if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
|
||||
if (mWindow != null) {
|
||||
mWindow.restoreViewVisibilityAfterTransitionToCallee();
|
||||
if (mCalledActivityOptions != null) {
|
||||
mCalledActivityOptions.dispatchActivityStopped();
|
||||
mCalledActivityOptions = null;
|
||||
}
|
||||
getApplication().dispatchActivityStopped(this);
|
||||
mTranslucentCallback = null;
|
||||
@@ -3484,7 +3490,7 @@ public class Activity extends ContextThemeWrapper
|
||||
public void startActivityForResult(Intent intent, int requestCode) {
|
||||
Bundle options = null;
|
||||
if (mWindow.hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
|
||||
options = ActivityOptions.makeSceneTransitionAnimation().toBundle();
|
||||
options = ActivityOptions.makeSceneTransitionAnimation(mWindow, null).toBundle();
|
||||
}
|
||||
startActivityForResult(intent, requestCode, options);
|
||||
}
|
||||
@@ -3526,14 +3532,8 @@ public class Activity extends ContextThemeWrapper
|
||||
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
|
||||
if (options != null) {
|
||||
ActivityOptions activityOptions = new ActivityOptions(options);
|
||||
if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
|
||||
if (mActionBar != null) {
|
||||
ArrayMap<String, View> sharedElementMap = new ArrayMap<String, View>();
|
||||
mActionBar.captureSharedElements(sharedElementMap);
|
||||
activityOptions.addSharedElements(sharedElementMap);
|
||||
}
|
||||
options = mWindow.startExitTransitionToCallee(options);
|
||||
}
|
||||
activityOptions.dispatchStartExit();
|
||||
mCalledActivityOptions = activityOptions;
|
||||
}
|
||||
if (mParent == null) {
|
||||
Instrumentation.ActivityResult ar =
|
||||
@@ -4391,16 +4391,15 @@ public class Activity extends ContextThemeWrapper
|
||||
* to reverse its exit Transition. When the exit Transition completes,
|
||||
* {@link #finish()} is called. If no entry Transition was used, finish() is called
|
||||
* immediately and the Activity exit Transition is run.
|
||||
* @see android.view.Window#setTriggerEarlySceneTransition(boolean, boolean)
|
||||
* @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.View, String)
|
||||
* @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.Window,
|
||||
* android.app.ActivityOptions.ActivityTransitionListener)
|
||||
*/
|
||||
public void finishWithTransition() {
|
||||
mWindow.startExitTransitionToCaller(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
if (mEnterTransitionCoordinator != null) {
|
||||
mEnterTransitionCoordinator.startExit();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5346,6 +5345,21 @@ public class Activity extends ContextThemeWrapper
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.Window,
|
||||
* android.app.ActivityOptions.ActivityTransitionListener)} was used to start an Activity,
|
||||
* the Window will be triggered to enter with a Transition. <code>listener</code> allows
|
||||
* The Activity to listen to events of the entering transition and control the mapping of
|
||||
* shared elements. This requires {@link Window#FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @param listener Used to listen to events in the entering transition.
|
||||
*/
|
||||
public void setActivityTransitionListener(ActivityOptions.ActivityTransitionListener listener) {
|
||||
if (mEnterTransitionCoordinator != null) {
|
||||
mEnterTransitionCoordinator.setActivityTransitionListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ Internal API ------------------
|
||||
|
||||
final void setParent(Activity parent) {
|
||||
@@ -5413,34 +5427,12 @@ public class Activity extends ContextThemeWrapper
|
||||
}
|
||||
mWindowManager = mWindow.getWindowManager();
|
||||
mCurrentConfig = config;
|
||||
Window.SceneTransitionListener sceneTransitionListener
|
||||
= new Window.SceneTransitionListener() {
|
||||
@Override
|
||||
public void nullPendingTransition() {
|
||||
overridePendingTransition(0, 0);
|
||||
if (options != null) {
|
||||
ActivityOptions activityOptions = new ActivityOptions(options);
|
||||
if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
|
||||
mEnterTransitionCoordinator = activityOptions.createEnterActivityTransition(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertFromTranslucent() {
|
||||
Activity.this.convertFromTranslucent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertToTranslucent() {
|
||||
Activity.this.convertToTranslucent(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sharedElementStart(Transition transition) {
|
||||
Activity.this.onCaptureSharedElementStart(transition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sharedElementEnd() {
|
||||
Activity.this.onCaptureSharedElementEnd();
|
||||
}
|
||||
};
|
||||
mWindow.setTransitionOptions(options, sceneTransitionListener);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@@ -5627,26 +5619,6 @@ public class Activity extends ContextThemeWrapper
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when setting up Activity Scene transitions when the start state for shared
|
||||
* elements has been captured. Override this method to modify the start position of shared
|
||||
* elements for the entry Transition.
|
||||
*
|
||||
* @param transition The <code>Transition</code> being used to change
|
||||
* bounds of shared elements in the source Activity to
|
||||
* the bounds defined by the entering Scene.
|
||||
*/
|
||||
public void onCaptureSharedElementStart(Transition transition) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when setting up Activity Scene transitions when the final state for
|
||||
* shared elements state has been captured. Override this method to modify the destination
|
||||
* position of shared elements for the entry Transition.
|
||||
*/
|
||||
public void onCaptureSharedElementEnd() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -20,16 +20,16 @@ import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.IRemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.transition.Transition;
|
||||
import android.util.Log;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -108,23 +108,6 @@ public class ActivityOptions {
|
||||
private static final String KEY_TRANSITION_COMPLETE_LISTENER
|
||||
= "android:transitionCompleteListener";
|
||||
|
||||
/**
|
||||
* For Activity transitions, the called Activity's listener to receive calls
|
||||
* when transitions complete.
|
||||
*/
|
||||
private static final String KEY_TRANSITION_TARGET_LISTENER = "android:transitionTargetListener";
|
||||
|
||||
/**
|
||||
* The names of shared elements that are transitioned to the started Activity.
|
||||
* This is also the name of shared elements that the started Activity accepted.
|
||||
*/
|
||||
private static final String KEY_SHARED_ELEMENT_NAMES = "android:shared_element_names";
|
||||
|
||||
/**
|
||||
* The shared elements names of the views in the calling Activity.
|
||||
*/
|
||||
private static final String KEY_LOCAL_ELEMENT_NAMES = "android:local_element_names";
|
||||
|
||||
/** @hide */
|
||||
public static final int ANIM_NONE = 0;
|
||||
/** @hide */
|
||||
@@ -138,11 +121,6 @@ public class ActivityOptions {
|
||||
/** @hide */
|
||||
public static final int ANIM_SCENE_TRANSITION = 5;
|
||||
|
||||
private static final int MSG_SET_LISTENER = 100;
|
||||
private static final int MSG_HIDE_SHARED_ELEMENTS = 101;
|
||||
private static final int MSG_PREPARE_RESTORE = 102;
|
||||
private static final int MSG_RESTORE = 103;
|
||||
|
||||
private String mPackageName;
|
||||
private int mAnimationType = ANIM_NONE;
|
||||
private int mCustomEnterResId;
|
||||
@@ -153,9 +131,7 @@ public class ActivityOptions {
|
||||
private int mStartWidth;
|
||||
private int mStartHeight;
|
||||
private IRemoteCallback mAnimationStartedListener;
|
||||
private ResultReceiver mTransitionCompleteListener;
|
||||
private ArrayList<String> mSharedElementNames;
|
||||
private ArrayList<String> mLocalElementNames;
|
||||
private ResultReceiver mExitReceiver;
|
||||
|
||||
/**
|
||||
* Create an ActivityOptions specifying a custom animation to run when
|
||||
@@ -231,12 +207,6 @@ public class ActivityOptions {
|
||||
void onAnimationStarted();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public interface ActivityTransitionTarget {
|
||||
void sharedElementTransitionComplete(Bundle transitionArgs);
|
||||
void exitTransitionComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ActivityOptions specifying an animation where the new
|
||||
* activity is scaled from a small originating area of the screen to
|
||||
@@ -357,49 +327,53 @@ public class ActivityOptions {
|
||||
/**
|
||||
* Create an ActivityOptions to transition between Activities using cross-Activity scene
|
||||
* animations. This method carries the position of one shared element to the started Activity.
|
||||
* The position of <code>sharedElement</code> will be used as the epicenter for the
|
||||
* exit Transition. The position of the shared element in the launched Activity will be the
|
||||
* epicenter of its entering Transition.
|
||||
*
|
||||
* <p>This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be
|
||||
* enabled on the calling Activity to cause an exit transition. The same must be in
|
||||
* the called Activity to get an entering transition.</p>
|
||||
* @param window The window containing shared elements.
|
||||
* @param sharedElement The View to transition to the started Activity. sharedElement must
|
||||
* have a non-null sharedElementName.
|
||||
* @param sharedElementName The shared element name as used in the target Activity. This may
|
||||
* be null if it has the same name as sharedElement.
|
||||
* @return Returns a new ActivityOptions object that you can use to
|
||||
* supply these options as the options Bundle when starting an activity.
|
||||
* @see android.transition.Transition#setEpicenterCallback(
|
||||
* android.transition.Transition.EpicenterCallback)
|
||||
*/
|
||||
public static ActivityOptions makeSceneTransitionAnimation(View sharedElement,
|
||||
String sharedElementName) {
|
||||
return makeSceneTransitionAnimation(
|
||||
new Pair<View, String>(sharedElement, sharedElementName));
|
||||
public static ActivityOptions makeSceneTransitionAnimation(Window window,
|
||||
View sharedElement, String sharedElementName) {
|
||||
return makeSceneTransitionAnimation(window,
|
||||
new SharedElementMappingListener(sharedElement, sharedElementName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ActivityOptions to transition between Activities using cross-Activity scene
|
||||
* animations. This method carries the position of multiple shared elements to the started
|
||||
* Activity.
|
||||
* Activity. The position of the first element in the value returned from
|
||||
* {@link android.app.ActivityOptions.ActivityTransitionListener#getSharedElementsMapping()}
|
||||
* will be used as the epicenter for the exit Transition. The position of the associated
|
||||
* shared element in the launched Activity will be the epicenter of its entering Transition.
|
||||
*
|
||||
* <p>This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be
|
||||
* enabled on the calling Activity to cause an exit transition. The same must be in
|
||||
* the called Activity to get an entering transition.</p>
|
||||
* @param sharedElements The View to transition to the started Activity along with the
|
||||
* shared element name as used in the started Activity. The view
|
||||
* must have a non-null sharedElementName.
|
||||
* @param window The window containing shared elements.
|
||||
* @param listener The listener to use to monitor activity transition events.
|
||||
* @return Returns a new ActivityOptions object that you can use to
|
||||
* supply these options as the options Bundle when starting an activity.
|
||||
* @see android.transition.Transition#setEpicenterCallback(
|
||||
* android.transition.Transition.EpicenterCallback)
|
||||
*/
|
||||
public static ActivityOptions makeSceneTransitionAnimation(
|
||||
Pair<View, String>... sharedElements) {
|
||||
public static ActivityOptions makeSceneTransitionAnimation(Window window,
|
||||
ActivityTransitionListener listener) {
|
||||
ActivityOptions opts = new ActivityOptions();
|
||||
opts.mAnimationType = ANIM_SCENE_TRANSITION;
|
||||
opts.mSharedElementNames = new ArrayList<String>();
|
||||
opts.mLocalElementNames = new ArrayList<String>();
|
||||
|
||||
if (sharedElements != null) {
|
||||
for (Pair<View, String> sharedElement : sharedElements) {
|
||||
opts.addSharedElement(sharedElement.first, sharedElement.second);
|
||||
}
|
||||
}
|
||||
ExitTransitionCoordinator exit = new ExitTransitionCoordinator(window, listener);
|
||||
opts.mExitReceiver = exit;
|
||||
return opts;
|
||||
}
|
||||
|
||||
@@ -435,9 +409,7 @@ public class ActivityOptions {
|
||||
break;
|
||||
|
||||
case ANIM_SCENE_TRANSITION:
|
||||
mTransitionCompleteListener = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER);
|
||||
mSharedElementNames = opts.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
|
||||
mLocalElementNames = opts.getStringArrayList(KEY_LOCAL_ELEMENT_NAMES);
|
||||
mExitReceiver = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -493,50 +465,16 @@ public class ActivityOptions {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public ArrayList<String> getSharedElementNames() { return mSharedElementNames; }
|
||||
|
||||
/** @hide */
|
||||
public ArrayList<String> getLocalElementNames() { return mLocalElementNames; }
|
||||
|
||||
/** @hide */
|
||||
public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target,
|
||||
ArrayList<String> sharedElementNames) {
|
||||
if (mTransitionCompleteListener != null) {
|
||||
IRemoteCallback callback = new IRemoteCallback.Stub() {
|
||||
@Override
|
||||
public void sendResult(Bundle data) throws RemoteException {
|
||||
if (data == null) {
|
||||
target.exitTransitionComplete();
|
||||
} else {
|
||||
target.sharedElementTransitionComplete(data);
|
||||
}
|
||||
}
|
||||
};
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBinder(KEY_TRANSITION_TARGET_LISTENER, callback.asBinder());
|
||||
bundle.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, sharedElementNames);
|
||||
mTransitionCompleteListener.send(MSG_SET_LISTENER, bundle);
|
||||
public void dispatchActivityStopped() {
|
||||
if (mExitReceiver != null) {
|
||||
mExitReceiver.send(ActivityTransitionCoordinator.MSG_ACTIVITY_STOPPED, null);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void dispatchSharedElementsReady() {
|
||||
if (mTransitionCompleteListener != null) {
|
||||
mTransitionCompleteListener.send(MSG_HIDE_SHARED_ELEMENTS, null);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void dispatchPrepareRestore() {
|
||||
if (mTransitionCompleteListener != null) {
|
||||
mTransitionCompleteListener.send(MSG_PREPARE_RESTORE, null);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void dispatchRestore(Bundle sharedElementsArgs) {
|
||||
if (mTransitionCompleteListener != null) {
|
||||
mTransitionCompleteListener.send(MSG_RESTORE, sharedElementsArgs);
|
||||
public void dispatchStartExit() {
|
||||
if (mExitReceiver != null) {
|
||||
mExitReceiver.send(ActivityTransitionCoordinator.MSG_START_EXIT_TRANSITION, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,6 +495,15 @@ public class ActivityOptions {
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public EnterTransitionCoordinator createEnterActivityTransition(Activity activity) {
|
||||
EnterTransitionCoordinator coordinator = null;
|
||||
if (mAnimationType == ANIM_SCENE_TRANSITION) {
|
||||
coordinator = new EnterTransitionCoordinator(activity, mExitReceiver);
|
||||
}
|
||||
return coordinator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the current values in this ActivityOptions from those supplied
|
||||
* in <var>otherOptions</var>. Any values
|
||||
@@ -566,8 +513,7 @@ public class ActivityOptions {
|
||||
if (otherOptions.mPackageName != null) {
|
||||
mPackageName = otherOptions.mPackageName;
|
||||
}
|
||||
mSharedElementNames = null;
|
||||
mLocalElementNames = null;
|
||||
mExitReceiver = null;
|
||||
switch (otherOptions.mAnimationType) {
|
||||
case ANIM_CUSTOM:
|
||||
mAnimationType = otherOptions.mAnimationType;
|
||||
@@ -581,7 +527,6 @@ public class ActivityOptions {
|
||||
}
|
||||
}
|
||||
mAnimationStartedListener = otherOptions.mAnimationStartedListener;
|
||||
mTransitionCompleteListener = null;
|
||||
break;
|
||||
case ANIM_SCALE_UP:
|
||||
mAnimationType = otherOptions.mAnimationType;
|
||||
@@ -596,7 +541,6 @@ public class ActivityOptions {
|
||||
}
|
||||
}
|
||||
mAnimationStartedListener = null;
|
||||
mTransitionCompleteListener = null;
|
||||
break;
|
||||
case ANIM_THUMBNAIL_SCALE_UP:
|
||||
case ANIM_THUMBNAIL_SCALE_DOWN:
|
||||
@@ -611,15 +555,12 @@ public class ActivityOptions {
|
||||
}
|
||||
}
|
||||
mAnimationStartedListener = otherOptions.mAnimationStartedListener;
|
||||
mTransitionCompleteListener = null;
|
||||
break;
|
||||
case ANIM_SCENE_TRANSITION:
|
||||
mAnimationType = otherOptions.mAnimationType;
|
||||
mTransitionCompleteListener = otherOptions.mTransitionCompleteListener;
|
||||
mExitReceiver = otherOptions.mExitReceiver;
|
||||
mThumbnail = null;
|
||||
mAnimationStartedListener = null;
|
||||
mSharedElementNames = otherOptions.mSharedElementNames;
|
||||
mLocalElementNames = otherOptions.mLocalElementNames;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -663,11 +604,9 @@ public class ActivityOptions {
|
||||
break;
|
||||
case ANIM_SCENE_TRANSITION:
|
||||
b.putInt(KEY_ANIM_TYPE, mAnimationType);
|
||||
if (mTransitionCompleteListener != null) {
|
||||
b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionCompleteListener);
|
||||
if (mExitReceiver != null) {
|
||||
b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mExitReceiver);
|
||||
}
|
||||
b.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, mSharedElementNames);
|
||||
b.putStringArrayList(KEY_LOCAL_ELEMENT_NAMES, mLocalElementNames);
|
||||
break;
|
||||
}
|
||||
return b;
|
||||
@@ -687,130 +626,92 @@ public class ActivityOptions {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void addSharedElements(Map<String, View> sharedElements) {
|
||||
for (Map.Entry<String, View> entry : sharedElements.entrySet()) {
|
||||
addSharedElement(entry.getValue(), entry.getKey());
|
||||
}
|
||||
/**
|
||||
* Listener provided in
|
||||
* {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.Window,
|
||||
* android.app.ActivityOptions.ActivityTransitionListener)} or in
|
||||
* {@link android.app.Activity#setActivityTransitionListener(
|
||||
* android.app.ActivityOptions.ActivityTransitionListener)} to monitor the Activity transitions.
|
||||
* The events can be used to customize or override Activity Transition behavior.
|
||||
*/
|
||||
public static class ActivityTransitionListener {
|
||||
/**
|
||||
* Called when the enter Transition is ready to start, but hasn't started yet. If
|
||||
* {@link android.view.Window#getEnterTransition()} is non-null,
|
||||
* The entering views will be {@link View#INVISIBLE}.
|
||||
*/
|
||||
public void onEnterReady() {}
|
||||
|
||||
/**
|
||||
* Called when the remote exiting transition completes.
|
||||
*/
|
||||
public void onRemoteExitComplete() {}
|
||||
|
||||
/**
|
||||
* Called when the start state for shared elements is captured on enter.
|
||||
*/
|
||||
public void onCaptureSharedElementStart() {}
|
||||
|
||||
/**
|
||||
* Called when the end state for shared elements is captured on enter.
|
||||
*/
|
||||
public void onCaptureSharedElementEnd() {}
|
||||
|
||||
/**
|
||||
* Called when the enter Transition has been started.
|
||||
* @param sharedElementNames The names of shared elements that were transferred.
|
||||
* @param sharedElements The shared elements that were transferred.
|
||||
*/
|
||||
public void onStartEnterTransition(List<String> sharedElementNames,
|
||||
List<View> sharedElements) {}
|
||||
|
||||
/**
|
||||
* Called when the exit Transition has been started.
|
||||
* @param sharedElementNames The names of all shared elements that will be transferred.
|
||||
* @param sharedElements All shared elements that will be transferred.
|
||||
*/
|
||||
public void onStartExitTransition(List<String> sharedElementNames,
|
||||
List<View> sharedElements) {}
|
||||
|
||||
/**
|
||||
* Called when the exiting shared element transition completes.
|
||||
*/
|
||||
public void onSharedElementExitTransitionComplete() {}
|
||||
|
||||
/**
|
||||
* Called on exit when the shared element has been transferred.
|
||||
* @param sharedElementNames The names of all shared elements that were transferred.
|
||||
* @param sharedElements All shared elements that will were transferred.
|
||||
*/
|
||||
public void onSharedElementTransferred(List<String> sharedElementNames,
|
||||
List<View> sharedElements) {}
|
||||
|
||||
/**
|
||||
* Called when the exit transition has completed.
|
||||
*/
|
||||
public void onExitTransitionComplete() {}
|
||||
|
||||
/**
|
||||
* Returns a mapping from a View in the View hierarchy to the shared element name used
|
||||
* in the call. This is called twice -- once when the view is
|
||||
* entering and again when it exits. A null return value indicates that the
|
||||
* View hierachy can be trusted without any remapping.
|
||||
* @return A map from a View in the hierarchy to the shared element name used in the
|
||||
* call.
|
||||
*/
|
||||
public Pair<View, String>[] getSharedElementsMapping() { return null; }
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void updateSceneTransitionAnimation(Transition exitTransition,
|
||||
Transition sharedElementTransition, SharedElementSource sharedElementSource) {
|
||||
mTransitionCompleteListener = new ExitTransitionListener(exitTransition,
|
||||
sharedElementTransition, sharedElementSource);
|
||||
}
|
||||
private static class SharedElementMappingListener extends ActivityTransitionListener {
|
||||
Pair<View, String>[] mSharedElementsMapping = new Pair[1];
|
||||
|
||||
private void addSharedElement(View view, String name) {
|
||||
String sharedElementName = view.getSharedElementName();
|
||||
if (name == null) {
|
||||
name = sharedElementName;
|
||||
}
|
||||
mSharedElementNames.add(name);
|
||||
mLocalElementNames.add(sharedElementName);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public interface SharedElementSource {
|
||||
Bundle getSharedElementExitState();
|
||||
void acceptedSharedElements(ArrayList<String> sharedElementNames);
|
||||
void hideSharedElements();
|
||||
void restore(Bundle sharedElementState);
|
||||
void prepareForRestore();
|
||||
}
|
||||
|
||||
private static class ExitTransitionListener extends ResultReceiver
|
||||
implements Transition.TransitionListener {
|
||||
private boolean mSharedElementNotified;
|
||||
private IRemoteCallback mTransitionCompleteCallback;
|
||||
private boolean mExitComplete;
|
||||
private boolean mSharedElementComplete;
|
||||
private SharedElementSource mSharedElementSource;
|
||||
|
||||
public ExitTransitionListener(Transition exitTransition, Transition sharedElementTransition,
|
||||
SharedElementSource sharedElementSource) {
|
||||
super(null);
|
||||
mSharedElementSource = sharedElementSource;
|
||||
exitTransition.addListener(this);
|
||||
sharedElementTransition.addListener(new Transition.TransitionListenerAdapter() {
|
||||
@Override
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
mSharedElementComplete = true;
|
||||
notifySharedElement();
|
||||
transition.removeListener(this);
|
||||
}
|
||||
});
|
||||
public SharedElementMappingListener(View view, String name) {
|
||||
mSharedElementsMapping[0] = Pair.create(view, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||
switch (resultCode) {
|
||||
case MSG_SET_LISTENER:
|
||||
IBinder listener = resultData.getBinder(KEY_TRANSITION_TARGET_LISTENER);
|
||||
mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface(listener);
|
||||
ArrayList<String> sharedElementNames
|
||||
= resultData.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
|
||||
mSharedElementSource.acceptedSharedElements(sharedElementNames);
|
||||
notifySharedElement();
|
||||
notifyExit();
|
||||
break;
|
||||
case MSG_HIDE_SHARED_ELEMENTS:
|
||||
mSharedElementSource.hideSharedElements();
|
||||
break;
|
||||
case MSG_PREPARE_RESTORE:
|
||||
mSharedElementSource.prepareForRestore();
|
||||
break;
|
||||
case MSG_RESTORE:
|
||||
mSharedElementSource.restore(resultData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionStart(Transition transition) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
mExitComplete = true;
|
||||
notifyExit();
|
||||
transition.removeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionCancel(Transition transition) {
|
||||
onTransitionEnd(transition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionPause(Transition transition) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionResume(Transition transition) {
|
||||
}
|
||||
|
||||
private void notifySharedElement() {
|
||||
if (!mSharedElementNotified && mSharedElementComplete
|
||||
&& mTransitionCompleteCallback != null) {
|
||||
mSharedElementNotified = true;
|
||||
try {
|
||||
Bundle sharedElementState = mSharedElementSource.getSharedElementExitState();
|
||||
mTransitionCompleteCallback.sendResult(sharedElementState);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Couldn't notify that the transition ended", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyExit() {
|
||||
if (mExitComplete && mTransitionCompleteCallback != null) {
|
||||
try {
|
||||
mTransitionCompleteCallback.sendResult(null);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Couldn't notify that the transition ended", e);
|
||||
}
|
||||
}
|
||||
public Pair<View, String>[] getSharedElementsMapping() {
|
||||
return mSharedElementsMapping;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
736
core/java/android/app/ActivityTransitionCoordinator.java
Normal file
736
core/java/android/app/ActivityTransitionCoordinator.java
Normal file
@@ -0,0 +1,736 @@
|
||||
/*
|
||||
* 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.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.ResultReceiver;
|
||||
import android.transition.Transition;
|
||||
import android.transition.TransitionManager;
|
||||
import android.transition.TransitionSet;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.Window;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Base class for ExitTransitionCoordinator and EnterTransitionCoordinator, classes
|
||||
* that manage activity transitions and the communications coordinating them between
|
||||
* Activities. The ExitTransitionCoordinator is created in the
|
||||
* ActivityOptions#makeSceneTransitionAnimation. The EnterTransitionCoordinator
|
||||
* is created by ActivityOptions#createEnterActivityTransition by Activity when the window is
|
||||
* attached.
|
||||
*
|
||||
* Typical startActivity goes like this:
|
||||
* 1) ExitTransitionCoordinator created with ActivityOptions#makeSceneTransitionAnimation
|
||||
* 2) Activity#startActivity called and that calls startExit() through
|
||||
* ActivityOptions#dispatchStartExit
|
||||
* - Exit transition starts by setting transitioning Views to INVISIBLE
|
||||
* 3) Launched Activity starts, creating an EnterTransitionCoordinator.
|
||||
* - The Window is made translucent
|
||||
* - The Window background alpha is set to 0
|
||||
* - The transitioning views are made INVISIBLE
|
||||
* - MSG_SET_LISTENER is sent back to the ExitTransitionCoordinator.
|
||||
* 4) The shared element transition completes.
|
||||
* - MSG_TAKE_SHARED_ELEMENTS is sent to the EnterTransitionCoordinator
|
||||
* 5) The MSG_TAKE_SHARED_ELEMENTS is received by the EnterTransitionCoordinator.
|
||||
* - Shared elements are made VISIBLE
|
||||
* - Shared elements positions and size are set to match the end state of the calling
|
||||
* Activity.
|
||||
* - The shared element transition is started
|
||||
* - If the window allows overlapping transitions, the views transition is started by setting
|
||||
* the entering Views to VISIBLE and the background alpha is animated to opaque.
|
||||
* - MSG_HIDE_SHARED_ELEMENTS is sent to the ExitTransitionCoordinator
|
||||
* 6) MSG_HIDE_SHARED_ELEMENTS is received by the ExitTransitionCoordinator
|
||||
* - The shared elements are made INVISIBLE
|
||||
* 7) The exit transition completes in the calling Activity.
|
||||
* - MSG_EXIT_TRANSITION_COMPLETE is sent to the EnterTransitionCoordinator.
|
||||
* 8) The MSG_EXIT_TRANSITION_COMPLETE is received by the EnterTransitionCoordinator.
|
||||
* - If the window doesn't allow overlapping enter transitions, the enter transition is started
|
||||
* by setting entering views to VISIBLE and the background is animated to opaque.
|
||||
* 9) The background opacity animation completes.
|
||||
* - The window is made opaque
|
||||
* 10) The calling Activity gets an onStop() call
|
||||
* - onActivityStopped() is called and all exited Views are made VISIBLE.
|
||||
*
|
||||
* Typical finishWithTransition goes like this:
|
||||
* 1) finishWithTransition() calls startExit()
|
||||
* - The Window start transitioning to Translucent
|
||||
* - If no background exists, a black background is substituted
|
||||
* - MSG_PREPARE_RESTORE is sent to the ExitTransitionCoordinator
|
||||
* - The shared elements in the scene are matched against those shared elements
|
||||
* that were sent by comparing the names.
|
||||
* - The exit transition is started by setting Views to INVISIBLE.
|
||||
* 2) MSG_PREPARE_RESTORE is received by the EnterTransitionCoordinator
|
||||
* - All transitioning views are made VISIBLE to reverse what was done when onActivityStopped()
|
||||
* was called
|
||||
* 3) The Window is made translucent and a callback is received
|
||||
* - The background alpha is animated to 0
|
||||
* 4) The background alpha animation completes
|
||||
* 5) The shared element transition completes
|
||||
* - After both 4 & 5 complete, MSG_TAKE_SHARED_ELEMENTS is sent to the
|
||||
* ExitTransitionCoordinator
|
||||
* 6) MSG_TAKE_SHARED_ELEMENTS is received by ExitTransitionCoordinator
|
||||
* - Shared elements are made VISIBLE
|
||||
* - Shared elements positions and size are set to match the end state of the calling
|
||||
* Activity.
|
||||
* - The shared element transition is started
|
||||
* - If the window allows overlapping transitions, the views transition is started by setting
|
||||
* the entering Views to VISIBLE.
|
||||
* - MSG_HIDE_SHARED_ELEMENTS is sent to the EnterTransitionCoordinator
|
||||
* 7) MSG_HIDE_SHARED_ELEMENTS is received by the EnterTransitionCoordinator
|
||||
* - The shared elements are made INVISIBLE
|
||||
* 8) The exit transition completes in the finishing Activity.
|
||||
* - MSG_EXIT_TRANSITION_COMPLETE is sent to the ExitTransitionCoordinator.
|
||||
* - finish() is called on the exiting Activity
|
||||
* 9) The MSG_EXIT_TRANSITION_COMPLETE is received by the ExitTransitionCoordinator.
|
||||
* - If the window doesn't allow overlapping enter transitions, the enter transition is started
|
||||
* by setting entering views to VISIBLE.
|
||||
*/
|
||||
abstract class ActivityTransitionCoordinator extends ResultReceiver {
|
||||
private static final String TAG = "ActivityTransitionCoordinator";
|
||||
|
||||
/**
|
||||
* The names of shared elements that are transitioned to the started Activity.
|
||||
* This is also the name of shared elements that the started Activity accepted.
|
||||
*/
|
||||
public static final String KEY_SHARED_ELEMENT_NAMES = "android:shared_element_names";
|
||||
|
||||
public static final String KEY_SHARED_ELEMENT_STATE = "android:shared_element_state";
|
||||
|
||||
/**
|
||||
* For Activity transitions, the called Activity's listener to receive calls
|
||||
* when transitions complete.
|
||||
*/
|
||||
static final String KEY_TRANSITION_RESULTS_RECEIVER = "android:transitionTargetListener";
|
||||
|
||||
private static final String KEY_SCREEN_X = "shared_element:screenX";
|
||||
private static final String KEY_SCREEN_Y = "shared_element:screenY";
|
||||
private static final String KEY_TRANSLATION_Z = "shared_element:translationZ";
|
||||
private static final String KEY_WIDTH = "shared_element:width";
|
||||
private static final String KEY_HEIGHT = "shared_element:height";
|
||||
private static final String KEY_NAME = "shared_element:name";
|
||||
|
||||
/**
|
||||
* Sent by the exiting coordinator (either EnterTransitionCoordinator
|
||||
* or ExitTransitionCoordinator) after the shared elements have
|
||||
* become stationary (shared element transition completes). This tells
|
||||
* the remote coordinator to take control of the shared elements and
|
||||
* that animations may begin. The remote Activity won't start entering
|
||||
* until this message is received, but may wait for
|
||||
* MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true.
|
||||
*/
|
||||
public static final int MSG_SET_LISTENER = 100;
|
||||
|
||||
/**
|
||||
* Sent by the entering coordinator to tell the exiting coordinator
|
||||
* to hide its shared elements after it has started its shared
|
||||
* element transition. This is temporary until the
|
||||
* interlock of shared elements is figured out.
|
||||
*/
|
||||
public static final int MSG_HIDE_SHARED_ELEMENTS = 101;
|
||||
|
||||
/**
|
||||
* Sent by the EnterTransitionCoordinator to tell the
|
||||
* ExitTransitionCoordinator to hide all of its exited views after
|
||||
* MSG_ACTIVITY_STOPPED has caused them all to show.
|
||||
*/
|
||||
public static final int MSG_PREPARE_RESTORE = 102;
|
||||
|
||||
/**
|
||||
* Sent by the exiting Activity in ActivityOptions#dispatchActivityStopped
|
||||
* to leave the Activity in a good state after it has been hidden.
|
||||
*/
|
||||
public static final int MSG_ACTIVITY_STOPPED = 103;
|
||||
|
||||
/**
|
||||
* Sent by the exiting coordinator (either EnterTransitionCoordinator
|
||||
* or ExitTransitionCoordinator) after the shared elements have
|
||||
* become stationary (shared element transition completes). This tells
|
||||
* the remote coordinator to take control of the shared elements and
|
||||
* that animations may begin. The remote Activity won't start entering
|
||||
* until this message is received, but may wait for
|
||||
* MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true.
|
||||
*/
|
||||
public static final int MSG_TAKE_SHARED_ELEMENTS = 104;
|
||||
|
||||
/**
|
||||
* Sent by the exiting coordinator (either
|
||||
* EnterTransitionCoordinator or ExitTransitionCoordinator) after
|
||||
* the exiting Views have finished leaving the scene. This will
|
||||
* be ignored if allowOverlappingTransitions() is true on the
|
||||
* remote coordinator. If it is false, it will trigger the enter
|
||||
* transition to start.
|
||||
*/
|
||||
public static final int MSG_EXIT_TRANSITION_COMPLETE = 105;
|
||||
|
||||
/**
|
||||
* Sent by Activity#startActivity to begin the exit transition.
|
||||
*/
|
||||
public static final int MSG_START_EXIT_TRANSITION = 106;
|
||||
|
||||
private Window mWindow;
|
||||
private ArrayList<View> mSharedElements = new ArrayList<View>();
|
||||
private ArrayList<String> mTargetSharedNames = new ArrayList<String>();
|
||||
private ActivityOptions.ActivityTransitionListener mListener =
|
||||
new ActivityOptions.ActivityTransitionListener();
|
||||
private ArrayList<View> mEnteringViews;
|
||||
private ResultReceiver mRemoteResultReceiver;
|
||||
private boolean mNotifiedSharedElementTransitionComplete;
|
||||
private boolean mNotifiedExitTransitionComplete;
|
||||
|
||||
private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback();
|
||||
|
||||
private Transition.TransitionListener mSharedElementListener =
|
||||
new Transition.TransitionListenerAdapter() {
|
||||
@Override
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
transition.removeListener(this);
|
||||
onSharedElementTransitionEnd();
|
||||
}
|
||||
};
|
||||
|
||||
private Transition.TransitionListener mExitListener =
|
||||
new Transition.TransitionListenerAdapter() {
|
||||
@Override
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
transition.removeListener(this);
|
||||
onExitTransitionEnd();
|
||||
}
|
||||
};
|
||||
|
||||
public ActivityTransitionCoordinator(Window window)
|
||||
{
|
||||
super(new Handler());
|
||||
mWindow = window;
|
||||
}
|
||||
|
||||
// -------------------- ResultsReceiver Overrides ----------------------
|
||||
@Override
|
||||
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||
switch (resultCode) {
|
||||
case MSG_SET_LISTENER:
|
||||
ResultReceiver resultReceiver
|
||||
= resultData.getParcelable(KEY_TRANSITION_RESULTS_RECEIVER);
|
||||
setRemoteResultReceiver(resultReceiver);
|
||||
onSetResultReceiver();
|
||||
break;
|
||||
case MSG_HIDE_SHARED_ELEMENTS:
|
||||
onHideSharedElements();
|
||||
break;
|
||||
case MSG_PREPARE_RESTORE:
|
||||
onPrepareRestore();
|
||||
break;
|
||||
case MSG_EXIT_TRANSITION_COMPLETE:
|
||||
onRemoteSceneExitComplete();
|
||||
break;
|
||||
case MSG_TAKE_SHARED_ELEMENTS:
|
||||
ArrayList<String> sharedElementNames
|
||||
= resultData.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
|
||||
Bundle sharedElementState = resultData.getBundle(KEY_SHARED_ELEMENT_STATE);
|
||||
onTakeSharedElements(sharedElementNames, sharedElementState);
|
||||
break;
|
||||
case MSG_ACTIVITY_STOPPED:
|
||||
onActivityStopped();
|
||||
break;
|
||||
case MSG_START_EXIT_TRANSITION:
|
||||
startExit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------- calls that can be overridden by subclasses --------------------
|
||||
|
||||
/**
|
||||
* Called when MSG_SET_LISTENER is received. This will only be received by
|
||||
* ExitTransitionCoordinator.
|
||||
*/
|
||||
protected void onSetResultReceiver() {}
|
||||
|
||||
/**
|
||||
* Called when MSG_HIDE_SHARED_ELEMENTS is received
|
||||
*/
|
||||
protected void onHideSharedElements() {
|
||||
setViewVisibility(getSharedElements(), View.INVISIBLE);
|
||||
mListener.onSharedElementTransferred(getSharedElementNames(), getSharedElements());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when MSG_PREPARE_RESTORE is called. This will only be received by
|
||||
* ExitTransitionCoordinator.
|
||||
*/
|
||||
protected void onPrepareRestore() {
|
||||
mListener.onEnterReady();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when MSG_EXIT_TRANSITION_COMPLETE is received -- the remote coordinator has
|
||||
* completed its exit transition. This can be called by the ExitTransitionCoordinator when
|
||||
* starting an Activity or EnterTransitionCoordinator when called with finishWithTransition.
|
||||
*/
|
||||
protected void onRemoteSceneExitComplete() {
|
||||
if (!allowOverlappingTransitions()) {
|
||||
Transition transition = beginTransition(mEnteringViews, false, true, true);
|
||||
onStartEnterTransition(transition, mEnteringViews);
|
||||
}
|
||||
mListener.onRemoteExitComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when MSG_TAKE_SHARED_ELEMENTS is received. This means that the shared elements are
|
||||
* in a stable state and ready to move to the Window.
|
||||
* @param sharedElementNames The names of the shared elements to move.
|
||||
* @param state Contains the shared element states (size & position)
|
||||
*/
|
||||
protected void onTakeSharedElements(ArrayList<String> sharedElementNames, Bundle state) {
|
||||
setSharedElements();
|
||||
reconcileSharedElements(sharedElementNames);
|
||||
mEnteringViews.removeAll(mSharedElements);
|
||||
setSharedElementState(state);
|
||||
if (getViewsTransition() != null) {
|
||||
setViewVisibility(mEnteringViews, View.INVISIBLE);
|
||||
}
|
||||
setViewVisibility(mSharedElements, View.VISIBLE);
|
||||
Transition transition = beginTransition(mEnteringViews, true, allowOverlappingTransitions(),
|
||||
true);
|
||||
if (allowOverlappingTransitions()) {
|
||||
onStartEnterTransition(transition, mEnteringViews);
|
||||
}
|
||||
mRemoteResultReceiver.send(MSG_HIDE_SHARED_ELEMENTS, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when MSG_ACTIVITY_STOPPED is received. This is received when Activity.onStop is
|
||||
* called after running startActivity* is called using an Activity Transition.
|
||||
*/
|
||||
protected void onActivityStopped() {}
|
||||
|
||||
/**
|
||||
* Called when the start transition is ready to run. This may be immediately after
|
||||
* MSG_TAKE_SHARED_ELEMENTS or MSG_EXIT_TRANSITION_COMPLETE, depending on whether
|
||||
* overlapping transitions are allowed.
|
||||
* @param transition The transition currently started.
|
||||
* @param enteringViews The views entering the scene. This won't include shared elements.
|
||||
*/
|
||||
protected void onStartEnterTransition(Transition transition, ArrayList<View> enteringViews) {
|
||||
if (getViewsTransition() != null) {
|
||||
setViewVisibility(enteringViews, View.VISIBLE);
|
||||
}
|
||||
mEnteringViews = null;
|
||||
mListener.onStartEnterTransition(getSharedElementNames(), getSharedElements());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the exit transition has started.
|
||||
* @param exitingViews The views leaving the scene. This won't include shared elements.
|
||||
*/
|
||||
protected void onStartExitTransition(ArrayList<View> exitingViews) {}
|
||||
|
||||
/**
|
||||
* Called during the exit when the shared element transition has completed.
|
||||
*/
|
||||
protected void onSharedElementTransitionEnd() {
|
||||
Bundle bundle = new Bundle();
|
||||
int[] tempLoc = new int[2];
|
||||
for (int i = 0; i < mSharedElements.size(); i++) {
|
||||
View sharedElement = mSharedElements.get(i);
|
||||
String name = mTargetSharedNames.get(i);
|
||||
captureSharedElementState(sharedElement, name, bundle, tempLoc);
|
||||
}
|
||||
Bundle allValues = new Bundle();
|
||||
allValues.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, getSharedElementNames());
|
||||
allValues.putBundle(KEY_SHARED_ELEMENT_STATE, bundle);
|
||||
sharedElementTransitionComplete(allValues);
|
||||
mListener.onSharedElementExitTransitionComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the shared element transition is complete to pass the shared element state
|
||||
* to the remote coordinator.
|
||||
* @param bundle The Bundle to send to the coordinator containing the shared element state.
|
||||
*/
|
||||
protected abstract void sharedElementTransitionComplete(Bundle bundle);
|
||||
|
||||
/**
|
||||
* Called when the exit transition finishes.
|
||||
*/
|
||||
protected void onExitTransitionEnd() {
|
||||
mListener.onExitTransitionComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to start the exit transition. Launched from ActivityOptions#dispatchStartExit
|
||||
*/
|
||||
protected abstract void startExit();
|
||||
|
||||
/**
|
||||
* A non-null transition indicates that the Views of the Window should be made INVISIBLE.
|
||||
* @return The Transition used to cause transitioning views to either enter or exit the scene.
|
||||
*/
|
||||
protected abstract Transition getViewsTransition();
|
||||
|
||||
/**
|
||||
* @return The Transition used to move the shared elements from the start position and size
|
||||
* to the end position and size.
|
||||
*/
|
||||
protected abstract Transition getSharedElementTransition();
|
||||
|
||||
/**
|
||||
* @return When the enter transition should overlap with the exit transition of the
|
||||
* remote controller.
|
||||
*/
|
||||
protected abstract boolean allowOverlappingTransitions();
|
||||
|
||||
// called by subclasses
|
||||
|
||||
protected void notifySharedElementTransitionComplete(Bundle sharedElements) {
|
||||
if (!mNotifiedSharedElementTransitionComplete) {
|
||||
mNotifiedSharedElementTransitionComplete = true;
|
||||
mRemoteResultReceiver.send(MSG_TAKE_SHARED_ELEMENTS, sharedElements);
|
||||
}
|
||||
}
|
||||
|
||||
protected void notifyExitTransitionComplete() {
|
||||
if (!mNotifiedExitTransitionComplete) {
|
||||
mNotifiedExitTransitionComplete = true;
|
||||
mRemoteResultReceiver.send(MSG_EXIT_TRANSITION_COMPLETE, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void notifyPrepareRestore() {
|
||||
mRemoteResultReceiver.send(MSG_PREPARE_RESTORE, null);
|
||||
}
|
||||
|
||||
protected void setRemoteResultReceiver(ResultReceiver resultReceiver) {
|
||||
mRemoteResultReceiver = resultReceiver;
|
||||
}
|
||||
|
||||
protected void notifySetListener() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(KEY_TRANSITION_RESULTS_RECEIVER, this);
|
||||
mRemoteResultReceiver.send(MSG_SET_LISTENER, bundle);
|
||||
}
|
||||
|
||||
protected void setEnteringViews(ArrayList<View> views) {
|
||||
mEnteringViews = views;
|
||||
}
|
||||
|
||||
protected void setSharedElements() {
|
||||
Pair<View, String>[] sharedElements = mListener.getSharedElementsMapping();
|
||||
mSharedElements.clear();
|
||||
mTargetSharedNames.clear();
|
||||
if (sharedElements == null) {
|
||||
ArrayMap<String, View> map = new ArrayMap<String, View>();
|
||||
setViewVisibility(mEnteringViews, View.VISIBLE);
|
||||
getDecor().findSharedElements(map);
|
||||
setViewVisibility(mEnteringViews, View.INVISIBLE);
|
||||
for (int i = 0; i < map.size(); i++) {
|
||||
View view = map.valueAt(i);
|
||||
String name = map.keyAt(i);
|
||||
mSharedElements.add(view);
|
||||
mTargetSharedNames.add(name);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < sharedElements.length; i++) {
|
||||
Pair<View, String> viewStringPair = sharedElements[i];
|
||||
View view = viewStringPair.first;
|
||||
String name = viewStringPair.second;
|
||||
mSharedElements.add(view);
|
||||
mTargetSharedNames.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ArrayList<View> getSharedElements() {
|
||||
return mSharedElements;
|
||||
}
|
||||
|
||||
protected ArrayList<String> getSharedElementNames() {
|
||||
return mTargetSharedNames;
|
||||
}
|
||||
|
||||
protected Window getWindow() {
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
protected ViewGroup getDecor() {
|
||||
return (mWindow == null) ? null : (ViewGroup) mWindow.getDecorView();
|
||||
}
|
||||
|
||||
protected void startExitTransition(ArrayList<String> sharedElements) {
|
||||
setSharedElements();
|
||||
reconcileSharedElements(sharedElements);
|
||||
ArrayList<View> transitioningViews = captureTransitioningViews();
|
||||
beginTransition(transitioningViews, true, true, false);
|
||||
onStartExitTransition(transitioningViews);
|
||||
if (getViewsTransition() != null) {
|
||||
setViewVisibility(transitioningViews, View.INVISIBLE);
|
||||
}
|
||||
mListener.onStartExitTransition(getSharedElementNames(), getSharedElements());
|
||||
}
|
||||
|
||||
protected void clearConnections() {
|
||||
mRemoteResultReceiver = null;
|
||||
}
|
||||
|
||||
// public API
|
||||
|
||||
public void setActivityTransitionListener(ActivityOptions.ActivityTransitionListener listener) {
|
||||
if (listener == null) {
|
||||
mListener = new ActivityOptions.ActivityTransitionListener();
|
||||
} else {
|
||||
mListener = listener;
|
||||
}
|
||||
}
|
||||
|
||||
// private methods
|
||||
|
||||
private Transition configureTransition(Transition transition) {
|
||||
if (transition != null) {
|
||||
transition = transition.clone();
|
||||
transition.setEpicenterCallback(mEpicenterCallback);
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
private void reconcileSharedElements(ArrayList<String> sharedElementNames) {
|
||||
Rect epicenter = null;
|
||||
for (int i = mTargetSharedNames.size() - 1; i >= 0; i--) {
|
||||
if (!sharedElementNames.contains(mTargetSharedNames.get(i))) {
|
||||
mTargetSharedNames.remove(i);
|
||||
mSharedElements.remove(i);
|
||||
}
|
||||
}
|
||||
if (!mSharedElements.isEmpty()) {
|
||||
epicenter = calcEpicenter(mSharedElements.get(0));
|
||||
}
|
||||
mEpicenterCallback.setEpicenter(epicenter);
|
||||
}
|
||||
|
||||
private void setSharedElementState(Bundle sharedElementState) {
|
||||
if (sharedElementState != null) {
|
||||
int[] tempLoc = new int[2];
|
||||
for (int i = 0; i < mSharedElements.size(); i++) {
|
||||
View sharedElement = mSharedElements.get(i);
|
||||
String name = mTargetSharedNames.get(i);
|
||||
setSharedElementState(sharedElement, name, sharedElementState, tempLoc);
|
||||
}
|
||||
}
|
||||
mListener.onCaptureSharedElementStart();
|
||||
getDecor().getViewTreeObserver().addOnPreDrawListener(
|
||||
new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
mListener.onCaptureSharedElementEnd();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the captured values from a previous
|
||||
* {@link #captureSharedElementState(android.view.View, String, android.os.Bundle, int[])}
|
||||
* @param view The View to apply placement changes to.
|
||||
* @param name The shared element name given from the source Activity.
|
||||
* @param transitionArgs A <code>Bundle</code> containing all placementinformation for named
|
||||
* shared elements in the scene.
|
||||
* @param tempLoc A temporary int[2] for capturing the current location of views.
|
||||
*/
|
||||
private static void setSharedElementState(View view, String name, Bundle transitionArgs,
|
||||
int[] tempLoc) {
|
||||
Bundle sharedElementBundle = transitionArgs.getBundle(name);
|
||||
if (sharedElementBundle == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
|
||||
view.setTranslationZ(z);
|
||||
|
||||
int x = sharedElementBundle.getInt(KEY_SCREEN_X);
|
||||
int y = sharedElementBundle.getInt(KEY_SCREEN_Y);
|
||||
int width = sharedElementBundle.getInt(KEY_WIDTH);
|
||||
int height = sharedElementBundle.getInt(KEY_HEIGHT);
|
||||
|
||||
int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
|
||||
int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
|
||||
view.measure(widthSpec, heightSpec);
|
||||
|
||||
ViewGroup parent = (ViewGroup) view.getParent();
|
||||
parent.getLocationOnScreen(tempLoc);
|
||||
int left = x - tempLoc[0];
|
||||
int top = y - tempLoc[1];
|
||||
int right = left + width;
|
||||
int bottom = top + height;
|
||||
view.layout(left, top, right, bottom);
|
||||
|
||||
view.requestLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures placement information for Views with a shared element name for
|
||||
* Activity Transitions.
|
||||
* @param view The View to capture the placement information for.
|
||||
* @param name The shared element name in the target Activity to apply the placement
|
||||
* information for.
|
||||
* @param transitionArgs Bundle to store shared element placement information.
|
||||
* @param tempLoc A temporary int[2] for capturing the current location of views.
|
||||
* @see #setSharedElementState(android.view.View, String, android.os.Bundle, int[])
|
||||
*/
|
||||
private static void captureSharedElementState(View view, String name, Bundle transitionArgs,
|
||||
int[] tempLoc) {
|
||||
Bundle sharedElementBundle = new Bundle();
|
||||
view.getLocationOnScreen(tempLoc);
|
||||
float scaleX = view.getScaleX();
|
||||
sharedElementBundle.putInt(KEY_SCREEN_X, tempLoc[0]);
|
||||
int width = Math.round(view.getWidth() * scaleX);
|
||||
sharedElementBundle.putInt(KEY_WIDTH, width);
|
||||
|
||||
float scaleY = view.getScaleY();
|
||||
sharedElementBundle.putInt(KEY_SCREEN_Y, tempLoc[1]);
|
||||
int height= Math.round(view.getHeight() * scaleY);
|
||||
sharedElementBundle.putInt(KEY_HEIGHT, height);
|
||||
|
||||
sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ());
|
||||
|
||||
sharedElementBundle.putString(KEY_NAME, view.getSharedElementName());
|
||||
|
||||
transitionArgs.putBundle(name, sharedElementBundle);
|
||||
}
|
||||
|
||||
private static Rect calcEpicenter(View view) {
|
||||
int[] loc = new int[2];
|
||||
view.getLocationOnScreen(loc);
|
||||
int left = loc[0] + Math.round(view.getTranslationX());
|
||||
int top = loc[1] + Math.round(view.getTranslationY());
|
||||
int right = left + view.getWidth();
|
||||
int bottom = top + view.getHeight();
|
||||
return new Rect(left, top, right, bottom);
|
||||
}
|
||||
|
||||
public static void setViewVisibility(Collection<View> views, int visibility) {
|
||||
if (views != null) {
|
||||
for (View view : views) {
|
||||
view.setVisibility(visibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Transition addTransitionTargets(Transition transition, Collection<View> views) {
|
||||
if (transition == null || views == null || views.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
TransitionSet set = new TransitionSet();
|
||||
set.addTransition(transition.clone());
|
||||
if (views != null) {
|
||||
for (View view: views) {
|
||||
set.addTarget(view);
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
private ArrayList<View> captureTransitioningViews() {
|
||||
if (getViewsTransition() == null) {
|
||||
return null;
|
||||
}
|
||||
ArrayList<View> transitioningViews = new ArrayList<View>();
|
||||
getDecor().captureTransitioningViews(transitioningViews);
|
||||
transitioningViews.removeAll(getSharedElements());
|
||||
return transitioningViews;
|
||||
}
|
||||
|
||||
private Transition getSharedElementTransition(boolean isEnter) {
|
||||
Transition transition = getSharedElementTransition();
|
||||
if (transition == null) {
|
||||
return null;
|
||||
}
|
||||
transition = configureTransition(transition);
|
||||
if (!isEnter) {
|
||||
transition.addListener(mSharedElementListener);
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
private Transition getViewsTransition(ArrayList<View> transitioningViews, boolean isEnter) {
|
||||
Transition transition = getViewsTransition();
|
||||
if (transition == null) {
|
||||
return null;
|
||||
}
|
||||
transition = configureTransition(transition);
|
||||
if (!isEnter) {
|
||||
transition.addListener(mExitListener);
|
||||
}
|
||||
return addTransitionTargets(transition, transitioningViews);
|
||||
}
|
||||
|
||||
private Transition beginTransition(ArrayList<View> transitioningViews,
|
||||
boolean transitionSharedElement, boolean transitionViews, boolean isEnter) {
|
||||
Transition sharedElementTransition = null;
|
||||
if (transitionSharedElement) {
|
||||
sharedElementTransition = getSharedElementTransition(isEnter);
|
||||
if (!isEnter && sharedElementTransition == null) {
|
||||
onSharedElementTransitionEnd();
|
||||
}
|
||||
}
|
||||
Transition viewsTransition = null;
|
||||
if (transitionViews) {
|
||||
viewsTransition = getViewsTransition(transitioningViews, isEnter);
|
||||
if (!isEnter && viewsTransition == null) {
|
||||
onExitTransitionEnd();
|
||||
}
|
||||
}
|
||||
|
||||
Transition transition = null;
|
||||
if (sharedElementTransition == null) {
|
||||
transition = viewsTransition;
|
||||
} else if (viewsTransition == null) {
|
||||
transition = sharedElementTransition;
|
||||
} else {
|
||||
TransitionSet set = new TransitionSet();
|
||||
set.addTransition(sharedElementTransition);
|
||||
set.addTransition(viewsTransition);
|
||||
transition = set;
|
||||
}
|
||||
if (transition != null) {
|
||||
TransitionManager.beginDelayedTransition(getDecor(), transition);
|
||||
if (transitionSharedElement && !mSharedElements.isEmpty()) {
|
||||
mSharedElements.get(0).invalidate();
|
||||
} else if (transitionViews && !transitioningViews.isEmpty()) {
|
||||
transitioningViews.get(0).invalidate();
|
||||
}
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
|
||||
private Rect mEpicenter;
|
||||
|
||||
public void setEpicenter(Rect epicenter) { mEpicenter = epicenter; }
|
||||
|
||||
@Override
|
||||
public Rect getEpicenter(Transition transition) {
|
||||
return mEpicenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
292
core/java/android/app/EnterTransitionCoordinator.java
Normal file
292
core/java/android/app/EnterTransitionCoordinator.java
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* 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.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.ResultReceiver;
|
||||
import android.transition.Transition;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.Window;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This ActivityTransitionCoordinator is created by the Activity to manage
|
||||
* the enter scene and shared element transfer as well as Activity#finishWithTransition
|
||||
* exiting the Scene and transferring shared elements back to the called Activity.
|
||||
*/
|
||||
class EnterTransitionCoordinator extends ActivityTransitionCoordinator
|
||||
implements ViewTreeObserver.OnPreDrawListener {
|
||||
private static final String TAG = "EnterTransitionCoordinator";
|
||||
|
||||
// The background fade in/out duration. 150ms is pretty quick, but not abrupt.
|
||||
private static final int FADE_BACKGROUND_DURATION_MS = 150;
|
||||
|
||||
/**
|
||||
* The shared element names sent by the ExitTransitionCoordinator and may be
|
||||
* shared when exiting back.
|
||||
*/
|
||||
private ArrayList<String> mEnteringSharedElementNames;
|
||||
|
||||
/**
|
||||
* The Activity that has created this coordinator. This is used solely to make the
|
||||
* Window translucent/opaque.
|
||||
*/
|
||||
private Activity mActivity;
|
||||
|
||||
/**
|
||||
* True if the Window was opaque at the start and we should make it opaque again after
|
||||
* enter transitions have completed.
|
||||
*/
|
||||
private boolean mWasOpaque;
|
||||
|
||||
/**
|
||||
* During exit, is the background alpha == 0?
|
||||
*/
|
||||
private boolean mBackgroundFadedOut;
|
||||
|
||||
/**
|
||||
* During exit, has the shared element transition completed?
|
||||
*/
|
||||
private boolean mSharedElementTransitionComplete;
|
||||
|
||||
/**
|
||||
* Has the exit started? We don't want to accidentally exit multiple times. e.g. when
|
||||
* back is hit twice during the exit animation.
|
||||
*/
|
||||
private boolean mExitTransitionStarted;
|
||||
|
||||
/**
|
||||
* Has the exit transition ended?
|
||||
*/
|
||||
private boolean mExitTransitionComplete;
|
||||
|
||||
/**
|
||||
* We only want to make the Window transparent and set the background alpha once. After that,
|
||||
* the Activity won't want the same enter transition.
|
||||
*/
|
||||
private boolean mMadeReady;
|
||||
|
||||
/**
|
||||
* True if Window.hasFeature(Window.FEATURE_CONTENT_TRANSITIONS) -- this means that
|
||||
* enter and exit transitions should be active.
|
||||
*/
|
||||
private boolean mSupportsTransition;
|
||||
|
||||
/**
|
||||
* Background alpha animations may complete prior to receiving the callback for
|
||||
* onTranslucentConversionComplete. If so, we need to immediately call to make the Window
|
||||
* opaque.
|
||||
*/
|
||||
private boolean mMakeOpaque;
|
||||
|
||||
public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver) {
|
||||
super(activity.getWindow());
|
||||
mActivity = activity;
|
||||
setRemoteResultReceiver(resultReceiver);
|
||||
}
|
||||
|
||||
public void readyToEnter() {
|
||||
if (!mMadeReady) {
|
||||
mMadeReady = true;
|
||||
mSupportsTransition = getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS);
|
||||
if (mSupportsTransition) {
|
||||
Window window = getWindow();
|
||||
window.getDecorView().getViewTreeObserver().addOnPreDrawListener(this);
|
||||
mActivity.overridePendingTransition(0, 0);
|
||||
mActivity.convertToTranslucent(new Activity.TranslucentConversionListener() {
|
||||
@Override
|
||||
public void onTranslucentConversionComplete(boolean drawComplete) {
|
||||
mWasOpaque = true;
|
||||
if (mMakeOpaque) {
|
||||
mActivity.convertFromTranslucent();
|
||||
}
|
||||
}
|
||||
});
|
||||
Drawable background = getDecor().getBackground();
|
||||
if (background != null) {
|
||||
window.setBackgroundDrawable(null);
|
||||
background.setAlpha(0);
|
||||
window.setBackgroundDrawable(background);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemoteSceneExitComplete() {
|
||||
super.onRemoteSceneExitComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTakeSharedElements(ArrayList<String> sharedElementNames, Bundle state) {
|
||||
mEnteringSharedElementNames = new ArrayList<String>();
|
||||
mEnteringSharedElementNames.addAll(sharedElementNames);
|
||||
super.onTakeSharedElements(sharedElementNames, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sharedElementTransitionComplete(Bundle bundle) {
|
||||
notifySharedElementTransitionComplete(bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
getWindow().getDecorView().getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
setEnteringViews(readyEnteringViews());
|
||||
notifySetListener();
|
||||
onPrepareRestore();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startExit() {
|
||||
if (!mExitTransitionStarted) {
|
||||
mExitTransitionStarted = true;
|
||||
startExitTransition(mEnteringSharedElementNames);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Transition getViewsTransition() {
|
||||
if (!mSupportsTransition) {
|
||||
return null;
|
||||
}
|
||||
return getWindow().getEnterTransition();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Transition getSharedElementTransition() {
|
||||
if (!mSupportsTransition) {
|
||||
return null;
|
||||
}
|
||||
return getWindow().getSharedElementEnterTransition();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartEnterTransition(Transition transition, ArrayList<View> enteringViews) {
|
||||
Drawable background = getDecor().getBackground();
|
||||
if (background != null) {
|
||||
ObjectAnimator animator = ObjectAnimator.ofInt(background, "alpha", 255);
|
||||
animator.setDuration(FADE_BACKGROUND_DURATION_MS);
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mMakeOpaque = true;
|
||||
if (mWasOpaque) {
|
||||
mActivity.convertFromTranslucent();
|
||||
}
|
||||
}
|
||||
});
|
||||
animator.start();
|
||||
} else if (mWasOpaque) {
|
||||
transition.addListener(new Transition.TransitionListenerAdapter() {
|
||||
@Override
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
mMakeOpaque = true;
|
||||
mActivity.convertFromTranslucent();
|
||||
}
|
||||
});
|
||||
}
|
||||
super.onStartEnterTransition(transition, enteringViews);
|
||||
}
|
||||
|
||||
public ArrayList<View> readyEnteringViews() {
|
||||
ArrayList<View> enteringViews = new ArrayList<View>();
|
||||
getDecor().captureTransitioningViews(enteringViews);
|
||||
if (getViewsTransition() != null) {
|
||||
setViewVisibility(enteringViews, View.INVISIBLE);
|
||||
}
|
||||
return enteringViews;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startExitTransition(ArrayList<String> sharedElements) {
|
||||
notifyPrepareRestore();
|
||||
|
||||
if (getDecor().getBackground() == null) {
|
||||
ColorDrawable black = new ColorDrawable(0xFF000000);
|
||||
getWindow().setBackgroundDrawable(black);
|
||||
}
|
||||
if (mWasOpaque) {
|
||||
mActivity.convertToTranslucent(new Activity.TranslucentConversionListener() {
|
||||
@Override
|
||||
public void onTranslucentConversionComplete(boolean drawComplete) {
|
||||
fadeOutBackground();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
fadeOutBackground();
|
||||
}
|
||||
|
||||
super.startExitTransition(sharedElements);
|
||||
}
|
||||
|
||||
private void fadeOutBackground() {
|
||||
ObjectAnimator animator = ObjectAnimator.ofInt(getDecor().getBackground(),
|
||||
"alpha", 0);
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mBackgroundFadedOut = true;
|
||||
if (mSharedElementTransitionComplete) {
|
||||
EnterTransitionCoordinator.super.onSharedElementTransitionEnd();
|
||||
}
|
||||
}
|
||||
});
|
||||
animator.setDuration(FADE_BACKGROUND_DURATION_MS);
|
||||
animator.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onExitTransitionEnd() {
|
||||
mExitTransitionComplete = true;
|
||||
exitAfterSharedElementTransition();
|
||||
super.onExitTransitionEnd();
|
||||
clearConnections();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSharedElementTransitionEnd() {
|
||||
mSharedElementTransitionComplete = true;
|
||||
if (mBackgroundFadedOut) {
|
||||
super.onSharedElementTransitionEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean allowOverlappingTransitions() {
|
||||
return getWindow().getAllowEnterTransitionOverlap();
|
||||
}
|
||||
|
||||
private void exitAfterSharedElementTransition() {
|
||||
if (mSharedElementTransitionComplete && mExitTransitionComplete) {
|
||||
mActivity.finish();
|
||||
if (mSupportsTransition) {
|
||||
mActivity.overridePendingTransition(0, 0);
|
||||
}
|
||||
notifyExitTransitionComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
171
core/java/android/app/ExitTransitionCoordinator.java
Normal file
171
core/java/android/app/ExitTransitionCoordinator.java
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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.transition.Transition;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This ActivityTransitionCoordinator is created in ActivityOptions#makeSceneTransitionAnimation
|
||||
* to govern the exit of the Scene and the shared elements when calling an Activity as well as
|
||||
* the reentry of the Scene when coming back from the called Activity.
|
||||
*/
|
||||
class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
|
||||
private static final String TAG = "ExitTransitionCoordinator";
|
||||
|
||||
/**
|
||||
* The Views that have exited and need to be restored to VISIBLE when returning to the
|
||||
* normal state.
|
||||
*/
|
||||
private ArrayList<View> mTransitioningViews;
|
||||
|
||||
/**
|
||||
* Has the exit started? We don't want to accidentally exit multiple times.
|
||||
*/
|
||||
private boolean mExitStarted;
|
||||
|
||||
/**
|
||||
* Has the called Activity's ResultReceiver been set?
|
||||
*/
|
||||
private boolean mIsResultReceiverSet;
|
||||
|
||||
/**
|
||||
* Has the exit transition completed? If so, we can notify as soon as the ResultReceiver
|
||||
* has been set.
|
||||
*/
|
||||
private boolean mExitComplete;
|
||||
|
||||
/**
|
||||
* Has the shared element transition completed? If so, we can notify as soon as the
|
||||
* ResultReceiver has been set.
|
||||
*/
|
||||
private Bundle mSharedElements;
|
||||
|
||||
/**
|
||||
* Has the shared element transition completed?
|
||||
*/
|
||||
private boolean mSharedElementsComplete;
|
||||
|
||||
public ExitTransitionCoordinator(Window window,
|
||||
ActivityOptions.ActivityTransitionListener listener) {
|
||||
super(window);
|
||||
setActivityTransitionListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSetResultReceiver() {
|
||||
mIsResultReceiverSet = true;
|
||||
notifyCompletions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareRestore() {
|
||||
makeTransitioningViewsInvisible();
|
||||
setEnteringViews(mTransitioningViews);
|
||||
mTransitioningViews = null;
|
||||
super.onPrepareRestore();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTakeSharedElements(ArrayList<String> sharedElementNames, Bundle state) {
|
||||
super.onTakeSharedElements(sharedElementNames, state);
|
||||
clearConnections();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityStopped() {
|
||||
if (getViewsTransition() != null) {
|
||||
setViewVisibility(mTransitioningViews, View.VISIBLE);
|
||||
}
|
||||
super.onActivityStopped();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sharedElementTransitionComplete(Bundle bundle) {
|
||||
mSharedElements = bundle;
|
||||
mSharedElementsComplete = true;
|
||||
notifyCompletions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onExitTransitionEnd() {
|
||||
mExitComplete = true;
|
||||
notifyCompletions();
|
||||
super.onExitTransitionEnd();
|
||||
}
|
||||
|
||||
private void notifyCompletions() {
|
||||
if (mIsResultReceiverSet && mSharedElementsComplete) {
|
||||
if (mSharedElements != null) {
|
||||
notifySharedElementTransitionComplete(mSharedElements);
|
||||
mSharedElements = null;
|
||||
}
|
||||
if (mExitComplete) {
|
||||
notifyExitTransitionComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startExit() {
|
||||
if (!mExitStarted) {
|
||||
mExitStarted = true;
|
||||
setSharedElements();
|
||||
startExitTransition(getSharedElementNames());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Transition getViewsTransition() {
|
||||
if (!getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
|
||||
return null;
|
||||
}
|
||||
return getWindow().getExitTransition();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Transition getSharedElementTransition() {
|
||||
if (!getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
|
||||
return null;
|
||||
}
|
||||
return getWindow().getSharedElementExitTransition();
|
||||
}
|
||||
|
||||
private void makeTransitioningViewsInvisible() {
|
||||
if (getViewsTransition() != null) {
|
||||
setViewVisibility(mTransitioningViews, View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartExitTransition(ArrayList<View> exitingViews) {
|
||||
mTransitioningViews = new ArrayList<View>();
|
||||
if (exitingViews != null) {
|
||||
mTransitioningViews.addAll(exitingViews);
|
||||
}
|
||||
mTransitioningViews.addAll(getSharedElements());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean allowOverlappingTransitions() {
|
||||
return getWindow().getAllowExitTransitionOverlap();
|
||||
}
|
||||
}
|
||||
@@ -1585,7 +1585,7 @@ public abstract class Transition implements Cloneable {
|
||||
* hierarchy underneath it.
|
||||
*/
|
||||
void capturePropagationValues(TransitionValues transitionValues) {
|
||||
if (mPropagation != null) {
|
||||
if (mPropagation != null && !transitionValues.values.isEmpty()) {
|
||||
String[] propertyNames = mPropagation.getPropagationProperties();
|
||||
if (propertyNames == null) {
|
||||
return;
|
||||
|
||||
@@ -309,15 +309,11 @@ public class TransitionInflater {
|
||||
if (transitionId >= 0) {
|
||||
Transition transition = inflateTransition(transitionId);
|
||||
if (transition != null) {
|
||||
if (toScene == null) {
|
||||
throw new RuntimeException("No toScene for transition ID " + transitionId);
|
||||
}
|
||||
if (fromScene == null) {
|
||||
if (toScene == null) {
|
||||
throw new RuntimeException("No matching fromScene or toScene " +
|
||||
"for transition ID " + transitionId);
|
||||
} else {
|
||||
transitionManager.setTransition(toScene, transition);
|
||||
}
|
||||
} else if (toScene == null) {
|
||||
transitionManager.setExitTransition(fromScene, transition);
|
||||
transitionManager.setTransition(toScene, transition);
|
||||
} else {
|
||||
transitionManager.setTransition(fromScene, toScene, transition);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,6 @@ public class TransitionManager {
|
||||
private static final String[] EMPTY_STRINGS = new String[0];
|
||||
|
||||
ArrayMap<Scene, Transition> mSceneTransitions = new ArrayMap<Scene, Transition>();
|
||||
ArrayMap<Scene, Transition> mExitSceneTransitions = new ArrayMap<Scene, Transition>();
|
||||
ArrayMap<Scene, ArrayMap<Scene, Transition>> mScenePairTransitions =
|
||||
new ArrayMap<Scene, ArrayMap<Scene, Transition>>();
|
||||
private static ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>
|
||||
@@ -118,21 +117,6 @@ public class TransitionManager {
|
||||
mSceneTransitions.put(scene, transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a specific transition to occur when the given scene is exited. This
|
||||
* has the lowest priority -- if a Scene-to-Scene transition or
|
||||
* Scene enter transition can be applied, it will.
|
||||
*
|
||||
* @param scene The scene which, when exited, will cause the given
|
||||
* transition to run.
|
||||
* @param transition The transition that will play when the given scene is
|
||||
* exited. A value of null will result in the default behavior of
|
||||
* using the default transition instead.
|
||||
*/
|
||||
public void setExitTransition(Scene scene, Transition transition) {
|
||||
mExitSceneTransitions.put(scene, transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a specific transition to occur when the given pair of scenes is
|
||||
* exited/entered.
|
||||
@@ -181,9 +165,6 @@ public class TransitionManager {
|
||||
}
|
||||
}
|
||||
transition = mSceneTransitions.get(scene);
|
||||
if (transition == null && sceneRoot != null) {
|
||||
transition = mExitSceneTransitions.get(Scene.getCurrentScene(sceneRoot));
|
||||
}
|
||||
return (transition != null) ? transition : sDefaultTransition;
|
||||
}
|
||||
|
||||
@@ -238,34 +219,6 @@ public class TransitionManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the transition to a target defined scene if one has been
|
||||
* associated with this TransitionManager.
|
||||
*
|
||||
* @param toScene Target scene that this transition will move to
|
||||
* @return Transition corresponding to the given toScene or null
|
||||
* if no association exists in this TransitionManager
|
||||
*
|
||||
* @see #setTransition(Scene, Transition)
|
||||
* @hide
|
||||
*/
|
||||
public Transition getEnterTransition(Scene toScene) {
|
||||
return mSceneTransitions.get(toScene);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the transition from a defined scene to a target named scene if one has been
|
||||
* associated with this TransitionManager.
|
||||
*
|
||||
* @param fromScene Scene that this transition starts from
|
||||
* @return Transition corresponding to the given fromScene or null
|
||||
* if no association exists in this TransitionManager
|
||||
* @hide
|
||||
*/
|
||||
public Transition getExitTransition(Scene fromScene) {
|
||||
return mExitSceneTransitions.get(fromScene);
|
||||
}
|
||||
|
||||
/**
|
||||
* This private utility class is used to listen for both OnPreDraw and
|
||||
* OnAttachStateChange events. OnPreDraw events are the main ones we care
|
||||
|
||||
@@ -109,14 +109,14 @@ public abstract class Visibility extends Transition {
|
||||
final VisibilityInfo visInfo = new VisibilityInfo();
|
||||
visInfo.visibilityChange = false;
|
||||
visInfo.fadeIn = false;
|
||||
if (startValues != null) {
|
||||
if (startValues != null && startValues.values.containsKey(PROPNAME_VISIBILITY)) {
|
||||
visInfo.startVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY);
|
||||
visInfo.startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
|
||||
} else {
|
||||
visInfo.startVisibility = -1;
|
||||
visInfo.startParent = null;
|
||||
}
|
||||
if (endValues != null) {
|
||||
if (endValues != null && endValues.values.containsKey(PROPNAME_VISIBILITY)) {
|
||||
visInfo.endVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY);
|
||||
visInfo.endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
|
||||
} else {
|
||||
|
||||
@@ -2305,11 +2305,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
|
||||
/**
|
||||
* Changes whether or not this ViewGroup should be treated as a single entity during
|
||||
* ActivityTransitions.
|
||||
* Activity Transitions.
|
||||
* @param isTransitionGroup Whether or not the ViewGroup should be treated as a unit
|
||||
* in Activity transitions. If false, the ViewGroup won't transition,
|
||||
* only its children. If true, the entire ViewGroup will transition
|
||||
* together.
|
||||
* @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.Window,
|
||||
* android.app.ActivityOptions.ActivityTransitionListener)
|
||||
*/
|
||||
public void setTransitionGroup(boolean isTransitionGroup) {
|
||||
mGroupFlags |= FLAG_IS_TRANSITION_GROUP_SET;
|
||||
|
||||
@@ -32,8 +32,6 @@ import android.transition.Transition;
|
||||
import android.transition.TransitionManager;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Abstract base class for a top-level window look and behavior policy. An
|
||||
* instance of this class should be used as the top-level view added to the
|
||||
@@ -1385,86 +1383,132 @@ public abstract class Window {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set options that can affect the transition behavior within this window.
|
||||
* @param options Options to set or null for none
|
||||
* @hide
|
||||
* Sets the Transition that will be used to move Views into the initial scene. The entering
|
||||
* Views will be those that are regular Views or ViewGroups that have
|
||||
* {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
|
||||
* {@link android.transition.Visibility} as entering is governed by changing visibility from
|
||||
* {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null,
|
||||
* entering Views will remain unaffected.
|
||||
* @param transition The Transition to use to move Views into the initial Scene.
|
||||
*/
|
||||
public void setTransitionOptions(Bundle options, SceneTransitionListener listener) {
|
||||
}
|
||||
public void setEnterTransition(Transition transition) {}
|
||||
|
||||
/**
|
||||
* A callback for Window transitions to be told when the shared element is ready to be shown
|
||||
* and start the transition to its target location.
|
||||
* @hide
|
||||
* Sets the Transition that will be used to move Views out of the scene when starting a
|
||||
* new Activity. The exiting Views will be those that are regular Views or ViewGroups that
|
||||
* have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
|
||||
* {@link android.transition.Visibility} as exiting is governed by changing visibility
|
||||
* from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
|
||||
* remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
* @param transition The Transition to use to move Views out of the scene when calling a
|
||||
* new Activity.
|
||||
*/
|
||||
public interface SceneTransitionListener {
|
||||
void nullPendingTransition();
|
||||
void convertFromTranslucent();
|
||||
void convertToTranslucent();
|
||||
void sharedElementStart(Transition transition);
|
||||
void sharedElementEnd();
|
||||
}
|
||||
public void setExitTransition(Transition transition) {}
|
||||
|
||||
/**
|
||||
* Controls how the Activity's start Scene is faded in and when the enter scene
|
||||
* is triggered to start.
|
||||
* <p>When allow is true, the enter Scene will begin as soon as possible
|
||||
* and the background will fade in when all shared elements are ready to begin
|
||||
* transitioning. If allow is false, the Activity enter Scene and
|
||||
* background fade will be triggered when the calling Activity's exit transition
|
||||
* completes.</p>
|
||||
* @param allow Set to true to have the Activity enter scene transition in
|
||||
* as early as possible or set to false to wait for the calling
|
||||
* Activity to exit first. The default value is true.
|
||||
* Returns the transition used to move Views into the initial scene. The entering
|
||||
* Views will be those that are regular Views or ViewGroups that have
|
||||
* {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
|
||||
* {@link android.transition.Visibility} as entering is governed by changing visibility from
|
||||
* {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null,
|
||||
* entering Views will remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @return the Transition to use to move Views into the initial Scene.
|
||||
*/
|
||||
public void setAllowOverlappingEnterTransition(boolean allow) {
|
||||
}
|
||||
public Transition getEnterTransition() { return null; }
|
||||
|
||||
/**
|
||||
* Controls how the Activity's Scene fades out and when the calling Activity's
|
||||
* enter scene is triggered when finishing to return to a calling Activity.
|
||||
* <p>When allow is true, the Scene will fade out quickly
|
||||
* and inform the calling Activity to transition in when the fade completes.
|
||||
* When allow is false, the calling Activity will transition in after
|
||||
* the Activity's Scene has exited.
|
||||
* </p>
|
||||
* @param allow Set to true to have the Activity fade out as soon as possible
|
||||
* and transition in the calling Activity. The default value is
|
||||
* true.
|
||||
* Returns the Transition that will be used to move Views out of the scene when starting a
|
||||
* new Activity. The exiting Views will be those that are regular Views or ViewGroups that
|
||||
* have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
|
||||
* {@link android.transition.Visibility} as exiting is governed by changing visibility
|
||||
* from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
|
||||
* remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
* @return the Transition to use to move Views out of the scene when calling a
|
||||
* new Activity.
|
||||
*/
|
||||
public void setAllowOverlappingExitTransition(boolean allow) {
|
||||
}
|
||||
public Transition getExitTransition() { return null; }
|
||||
|
||||
/**
|
||||
* Start the exit transition.
|
||||
* @hide
|
||||
* Sets the Transition that will be used for shared elements transferred into the content
|
||||
* Scene. Typical Transitions will affect size and location, such as
|
||||
* {@link android.transition.MoveImage} and {@link android.transition.ChangeBounds}. A null
|
||||
* value will cause transferred shared elements to blink to the final position.
|
||||
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
* @param transition The Transition to use for shared elements transferred into the content
|
||||
* Scene.
|
||||
*/
|
||||
public Bundle startExitTransitionToCallee(Bundle options) {
|
||||
return null;
|
||||
}
|
||||
public void setSharedElementEnterTransition(Transition transition) {}
|
||||
|
||||
/**
|
||||
* Starts the transition back to the calling Activity.
|
||||
* onTransitionEnd will be called on the current thread if there is no exit transition.
|
||||
* @hide
|
||||
* Returns the Transition that will be used for shared elements transferred into the content
|
||||
* Scene. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
* @return Transition to use for sharend elements transferred into the content Scene.
|
||||
*/
|
||||
public void startExitTransitionToCaller(Runnable onTransitionEnd) {
|
||||
onTransitionEnd.run();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void restoreViewVisibilityAfterTransitionToCallee() {
|
||||
}
|
||||
public Transition getSharedElementEnterTransition() { return null; }
|
||||
|
||||
/**
|
||||
* On entering Activity Scene transitions, shared element names may be mapped from a
|
||||
* source Activity's specified name to a unique shared element name in the View hierarchy.
|
||||
* Under most circumstances, mapping is not necessary - a single View will have the
|
||||
* shared element name given by the calling Activity. However, if there are several similar
|
||||
* Views (e.g. in a ListView), the correct shared element must be mapped.
|
||||
* @param sharedElementNames A mapping from the calling Activity's assigned shared element
|
||||
* name to a unique shared element name in the View hierarchy.
|
||||
* Sets the Transition that will be used for shared elements after starting a new Activity
|
||||
* before the shared elements are transferred to the called Activity. If the shared elements
|
||||
* must animate during the exit transition, this Transition should be used. Upon completion,
|
||||
* the shared elements may be transferred to the started Activity.
|
||||
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
* @param transition The Transition to use for shared elements in the launching Window
|
||||
* prior to transferring to the launched Activity's Window.
|
||||
*/
|
||||
public void mapTransitionTargets(Map<String, String> sharedElementNames) {
|
||||
}
|
||||
public void setSharedElementExitTransition(Transition transition) {}
|
||||
|
||||
/**
|
||||
* Returns the Transition to use for shared elements in the launching Window prior
|
||||
* to transferring to the launched Activity's Window.
|
||||
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
|
||||
*
|
||||
* @return the Transition to use for shared elements in the launching Window prior
|
||||
* to transferring to the launched Activity's Window.
|
||||
*/
|
||||
public Transition getSharedElementExitTransition() { return null; }
|
||||
|
||||
/**
|
||||
* Controls how the transition set in
|
||||
* {@link #setEnterTransition(android.transition.Transition)} overlaps with the exit
|
||||
* transition of the calling Activity. When true, the transition will start as soon as possible.
|
||||
* When false, the transition will wait until the remote exiting transition completes before
|
||||
* starting.
|
||||
* @param allow true to start the enter transition when possible or false to
|
||||
* wait until the exiting transition completes.
|
||||
*/
|
||||
public void setAllowEnterTransitionOverlap(boolean allow) {}
|
||||
|
||||
/**
|
||||
* Returns how the transition set in
|
||||
* {@link #setEnterTransition(android.transition.Transition)} overlaps with the exit
|
||||
* transition of the calling Activity. When true, the transition will start as soon as possible.
|
||||
* When false, the transition will wait until the remote exiting transition completes before
|
||||
* starting.
|
||||
* @return true when the enter transition should start as soon as possible or false to
|
||||
* when it should wait until the exiting transition completes.
|
||||
*/
|
||||
public boolean getAllowEnterTransitionOverlap() { return true; }
|
||||
|
||||
/**
|
||||
* Controls how the transition set in
|
||||
* {@link #setExitTransition(android.transition.Transition)} overlaps with the exit
|
||||
* transition of the called Activity when reentering after if finishes. When true,
|
||||
* the transition will start as soon as possible. When false, the transition will wait
|
||||
* until the called Activity's exiting transition completes before starting.
|
||||
* @param allow true to start the transition when possible or false to wait until the
|
||||
* called Activity's exiting transition completes.
|
||||
*/
|
||||
public void setAllowExitTransitionOverlap(boolean allow) {}
|
||||
|
||||
/**
|
||||
* Returns how the transition set in
|
||||
* {@link #setExitTransition(android.transition.Transition)} overlaps with the exit
|
||||
* transition of the called Activity when reentering after if finishes. When true,
|
||||
* the transition will start as soon as possible. When false, the transition will wait
|
||||
* until the called Activity's exiting transition completes before starting.
|
||||
* @return true when the transition should start when possible or false when it should wait
|
||||
* until the called Activity's exiting transition completes.
|
||||
*/
|
||||
public boolean getAllowExitTransitionOverlap() { return true; }
|
||||
}
|
||||
|
||||
@@ -444,9 +444,4 @@ public class ToolbarActionBar extends ActionBar {
|
||||
mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSharedElements(Map<String, View> sharedElements) {
|
||||
mToolbar.findSharedElements(sharedElements);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,10 +362,6 @@ public class WindowDecorActionBar extends ActionBar {
|
||||
setSubtitle(mContext.getString(resId));
|
||||
}
|
||||
|
||||
public void captureSharedElements(Map<String, View> sharedElements) {
|
||||
mContainerView.findSharedElements(sharedElements);
|
||||
}
|
||||
|
||||
public void setSelectedNavigationItem(int position) {
|
||||
switch (mActionView.getNavigationMode()) {
|
||||
case NAVIGATION_MODE_TABS:
|
||||
|
||||
Reference in New Issue
Block a user