Adding support for cross-task hero transition
> Do not show starting window when using hero transition > When running cross-task, only play the enter animation > Allow transitions when using intent-sender Bug: 113071278 Test: atest cts/tests/tests/transition/src/android/transition/cts/ActivityTransitionTest.java atest cts/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java Change-Id: Id973d52412a9a2cde3ebcae3b718556c47dfff5d
This commit is contained in:
@@ -4678,7 +4678,7 @@ public class Activity extends ContextThemeWrapper
|
|||||||
if (decor != null) {
|
if (decor != null) {
|
||||||
decor.cancelPendingInputEvents();
|
decor.cancelPendingInputEvents();
|
||||||
}
|
}
|
||||||
if (options != null && !isTopOfTask()) {
|
if (options != null) {
|
||||||
mActivityTransitionState.startExitOutTransition(this, options);
|
mActivityTransitionState.startExitOutTransition(this, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4882,6 +4882,7 @@ public class Activity extends ContextThemeWrapper
|
|||||||
Bundle options)
|
Bundle options)
|
||||||
throws IntentSender.SendIntentException {
|
throws IntentSender.SendIntentException {
|
||||||
try {
|
try {
|
||||||
|
options = transferSpringboardActivityOptions(options);
|
||||||
String resolvedType = null;
|
String resolvedType = null;
|
||||||
if (fillInIntent != null) {
|
if (fillInIntent != null) {
|
||||||
fillInIntent.migrateExtraStreamToClipData();
|
fillInIntent.migrateExtraStreamToClipData();
|
||||||
@@ -4898,6 +4899,12 @@ public class Activity extends ContextThemeWrapper
|
|||||||
throw new IntentSender.SendIntentException();
|
throw new IntentSender.SendIntentException();
|
||||||
}
|
}
|
||||||
Instrumentation.checkStartActivityResult(result, null);
|
Instrumentation.checkStartActivityResult(result, null);
|
||||||
|
|
||||||
|
if (options != null) {
|
||||||
|
// Only when the options are not null, as the intent can point to something other
|
||||||
|
// than an Activity.
|
||||||
|
cancelInputsAndStartExitTransition(options);
|
||||||
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
if (requestCode >= 0) {
|
if (requestCode >= 0) {
|
||||||
@@ -6471,7 +6478,7 @@ public class Activity extends ContextThemeWrapper
|
|||||||
*
|
*
|
||||||
* @return true if this is the topmost, non-finishing activity in its task.
|
* @return true if this is the topmost, non-finishing activity in its task.
|
||||||
*/
|
*/
|
||||||
private boolean isTopOfTask() {
|
final boolean isTopOfTask() {
|
||||||
if (mToken == null || mWindow == null) {
|
if (mToken == null || mWindow == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,6 +193,13 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
|
|||||||
*/
|
*/
|
||||||
public static final int MSG_SHARED_ELEMENT_DESTINATION = 107;
|
public static final int MSG_SHARED_ELEMENT_DESTINATION = 107;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sent by Activity#startActivity to notify the entering activity that enter animation for
|
||||||
|
* back is allowed. If this message is not received, the default exit animation will run when
|
||||||
|
* backing out of an activity (instead of the 'reverse' shared element transition).
|
||||||
|
*/
|
||||||
|
public static final int MSG_ALLOW_RETURN_TRANSITION = 108;
|
||||||
|
|
||||||
private Window mWindow;
|
private Window mWindow;
|
||||||
final protected ArrayList<String> mAllSharedElementNames;
|
final protected ArrayList<String> mAllSharedElementNames;
|
||||||
final protected ArrayList<View> mSharedElements = new ArrayList<View>();
|
final protected ArrayList<View> mSharedElements = new ArrayList<View>();
|
||||||
@@ -346,8 +353,6 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
|
|||||||
return new ArrayList<View>(mSharedElements);
|
return new ArrayList<View>(mSharedElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<String> getAllSharedElementNames() { return mAllSharedElementNames; }
|
|
||||||
|
|
||||||
protected Transition setTargets(Transition transition, boolean add) {
|
protected Transition setTargets(Transition transition, boolean add) {
|
||||||
if (transition == null || (add &&
|
if (transition == null || (add &&
|
||||||
(mTransitioningViews == null || mTransitioningViews.isEmpty()))) {
|
(mTransitioningViews == null || mTransitioningViews.isEmpty()))) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import java.util.ArrayList;
|
|||||||
*/
|
*/
|
||||||
class ActivityTransitionState {
|
class ActivityTransitionState {
|
||||||
|
|
||||||
private static final String ENTERING_SHARED_ELEMENTS = "android:enteringSharedElements";
|
private static final String PENDING_EXIT_SHARED_ELEMENTS = "android:pendingExitSharedElements";
|
||||||
|
|
||||||
private static final String EXITING_MAPPED_FROM = "android:exitingMappedFrom";
|
private static final String EXITING_MAPPED_FROM = "android:exitingMappedFrom";
|
||||||
|
|
||||||
@@ -43,9 +43,9 @@ class ActivityTransitionState {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The shared elements that the calling Activity has said that they transferred to this
|
* The shared elements that the calling Activity has said that they transferred to this
|
||||||
* Activity.
|
* Activity and will be transferred back during exit animation.
|
||||||
*/
|
*/
|
||||||
private ArrayList<String> mEnteringNames;
|
private ArrayList<String> mPendingExitNames;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The names of shared elements that were shared to the called Activity.
|
* The names of shared elements that were shared to the called Activity.
|
||||||
@@ -112,8 +112,7 @@ class ActivityTransitionState {
|
|||||||
|
|
||||||
public int addExitTransitionCoordinator(ExitTransitionCoordinator exitTransitionCoordinator) {
|
public int addExitTransitionCoordinator(ExitTransitionCoordinator exitTransitionCoordinator) {
|
||||||
if (mExitTransitionCoordinators == null) {
|
if (mExitTransitionCoordinators == null) {
|
||||||
mExitTransitionCoordinators =
|
mExitTransitionCoordinators = new SparseArray<>();
|
||||||
new SparseArray<WeakReference<ExitTransitionCoordinator>>();
|
|
||||||
}
|
}
|
||||||
WeakReference<ExitTransitionCoordinator> ref = new WeakReference(exitTransitionCoordinator);
|
WeakReference<ExitTransitionCoordinator> ref = new WeakReference(exitTransitionCoordinator);
|
||||||
// clean up old references:
|
// clean up old references:
|
||||||
@@ -132,7 +131,7 @@ class ActivityTransitionState {
|
|||||||
public void readState(Bundle bundle) {
|
public void readState(Bundle bundle) {
|
||||||
if (bundle != null) {
|
if (bundle != null) {
|
||||||
if (mEnterTransitionCoordinator == null || mEnterTransitionCoordinator.isReturning()) {
|
if (mEnterTransitionCoordinator == null || mEnterTransitionCoordinator.isReturning()) {
|
||||||
mEnteringNames = bundle.getStringArrayList(ENTERING_SHARED_ELEMENTS);
|
mPendingExitNames = bundle.getStringArrayList(PENDING_EXIT_SHARED_ELEMENTS);
|
||||||
}
|
}
|
||||||
if (mEnterTransitionCoordinator == null) {
|
if (mEnterTransitionCoordinator == null) {
|
||||||
mExitingFrom = bundle.getStringArrayList(EXITING_MAPPED_FROM);
|
mExitingFrom = bundle.getStringArrayList(EXITING_MAPPED_FROM);
|
||||||
@@ -141,9 +140,21 @@ class ActivityTransitionState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the element names to be used for exit animation. It caches the list internally so
|
||||||
|
* that it is preserved through activty destroy and restore.
|
||||||
|
*/
|
||||||
|
private ArrayList<String> getPendingExitNames() {
|
||||||
|
if (mPendingExitNames == null && mEnterTransitionCoordinator != null) {
|
||||||
|
mPendingExitNames = mEnterTransitionCoordinator.getPendingExitSharedElementNames();
|
||||||
|
}
|
||||||
|
return mPendingExitNames;
|
||||||
|
}
|
||||||
|
|
||||||
public void saveState(Bundle bundle) {
|
public void saveState(Bundle bundle) {
|
||||||
if (mEnteringNames != null) {
|
ArrayList<String> pendingExitNames = getPendingExitNames();
|
||||||
bundle.putStringArrayList(ENTERING_SHARED_ELEMENTS, mEnteringNames);
|
if (pendingExitNames != null) {
|
||||||
|
bundle.putStringArrayList(PENDING_EXIT_SHARED_ELEMENTS, pendingExitNames);
|
||||||
}
|
}
|
||||||
if (mExitingFrom != null) {
|
if (mExitingFrom != null) {
|
||||||
bundle.putStringArrayList(EXITING_MAPPED_FROM, mExitingFrom);
|
bundle.putStringArrayList(EXITING_MAPPED_FROM, mExitingFrom);
|
||||||
@@ -226,7 +237,7 @@ class ActivityTransitionState {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mEnterTransitionCoordinator.namedViewsReady(null, null);
|
mEnterTransitionCoordinator.namedViewsReady(null, null);
|
||||||
mEnteringNames = mEnterTransitionCoordinator.getAllSharedElementNames();
|
mPendingExitNames = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
mExitingFrom = null;
|
mExitingFrom = null;
|
||||||
@@ -268,7 +279,7 @@ class ActivityTransitionState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
mEnteringNames = null;
|
mPendingExitNames = null;
|
||||||
mExitingFrom = null;
|
mExitingFrom = null;
|
||||||
mExitingTo = null;
|
mExitingTo = null;
|
||||||
mExitingToView = null;
|
mExitingToView = null;
|
||||||
@@ -296,7 +307,8 @@ class ActivityTransitionState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean startExitBackTransition(final Activity activity) {
|
public boolean startExitBackTransition(final Activity activity) {
|
||||||
if (mEnteringNames == null || mCalledExitCoordinator != null) {
|
ArrayList<String> pendingExitNames = getPendingExitNames();
|
||||||
|
if (pendingExitNames == null || mCalledExitCoordinator != null) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if (!mHasExited) {
|
if (!mHasExited) {
|
||||||
@@ -315,7 +327,7 @@ class ActivityTransitionState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mReturnExitCoordinator = new ExitTransitionCoordinator(activity,
|
mReturnExitCoordinator = new ExitTransitionCoordinator(activity,
|
||||||
activity.getWindow(), activity.mEnterTransitionListener, mEnteringNames,
|
activity.getWindow(), activity.mEnterTransitionListener, pendingExitNames,
|
||||||
null, null, true);
|
null, null, true);
|
||||||
if (enterViewsTransition != null && decor != null) {
|
if (enterViewsTransition != null && decor != null) {
|
||||||
enterViewsTransition.resume(decor);
|
enterViewsTransition.resume(decor);
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
|
|||||||
private OneShotPreDrawListener mViewsReadyListener;
|
private OneShotPreDrawListener mViewsReadyListener;
|
||||||
private final boolean mIsCrossTask;
|
private final boolean mIsCrossTask;
|
||||||
private Drawable mReplacedBackground;
|
private Drawable mReplacedBackground;
|
||||||
|
private ArrayList<String> mPendingExitNames;
|
||||||
|
|
||||||
public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver,
|
public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver,
|
||||||
ArrayList<String> sharedElementNames, boolean isReturning, boolean isCrossTask) {
|
ArrayList<String> sharedElementNames, boolean isReturning, boolean isCrossTask) {
|
||||||
@@ -249,6 +250,11 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
|
|||||||
case MSG_CANCEL:
|
case MSG_CANCEL:
|
||||||
cancel();
|
cancel();
|
||||||
break;
|
break;
|
||||||
|
case MSG_ALLOW_RETURN_TRANSITION:
|
||||||
|
if (!mIsCanceled) {
|
||||||
|
mPendingExitNames = mAllSharedElementNames;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,6 +262,10 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
|
|||||||
return mIsReturning && mResultReceiver != null;
|
return mIsReturning && mResultReceiver != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getPendingExitSharedElementNames() {
|
||||||
|
return mPendingExitNames;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is called onResume. If an Activity is resuming and the transitions
|
* This is called onResume. If an Activity is resuming and the transitions
|
||||||
* haven't started yet, force the views to appear. This is likely to be
|
* haven't started yet, force the views to appear. This is likely to be
|
||||||
|
|||||||
@@ -433,6 +433,11 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
|
|||||||
if (!mSharedElementNotified) {
|
if (!mSharedElementNotified) {
|
||||||
mSharedElementNotified = true;
|
mSharedElementNotified = true;
|
||||||
delayCancel();
|
delayCancel();
|
||||||
|
|
||||||
|
if (!mActivity.isTopOfTask()) {
|
||||||
|
mResultReceiver.send(MSG_ALLOW_RETURN_TRANSITION, null);
|
||||||
|
}
|
||||||
|
|
||||||
if (mListener == null) {
|
if (mListener == null) {
|
||||||
mResultReceiver.send(MSG_TAKE_SHARED_ELEMENTS, mSharedElementBundle);
|
mResultReceiver.send(MSG_TAKE_SHARED_ELEMENTS, mSharedElementBundle);
|
||||||
notifyExitComplete();
|
notifyExitComplete();
|
||||||
|
|||||||
@@ -2285,6 +2285,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
|||||||
// We don't show starting window for overlay activities.
|
// We don't show starting window for overlay activities.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (pendingOptions != null
|
||||||
|
&& pendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
|
||||||
|
// Don't show starting window when using shared element transition.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final CompatibilityInfo compatInfo =
|
final CompatibilityInfo compatInfo =
|
||||||
service.compatibilityInfoForPackageLocked(info.applicationInfo);
|
service.compatibilityInfoForPackageLocked(info.applicationInfo);
|
||||||
|
|||||||
Reference in New Issue
Block a user