summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt26
-rw-r--r--core/java/android/app/Activity.java93
-rw-r--r--core/java/android/app/ActivityOptions.java230
-rw-r--r--core/java/android/transition/Transition.java45
-rw-r--r--core/java/android/transition/TransitionInflater.java43
-rw-r--r--core/java/android/transition/TransitionManager.java150
-rw-r--r--core/java/android/view/View.java29
-rw-r--r--core/java/android/view/ViewGroup.java40
-rw-r--r--core/java/android/view/Window.java38
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java5
-rw-r--r--core/res/res/layout-xlarge/screen_action_bar.xml1
-rw-r--r--core/res/res/layout/screen_action_bar.xml1
-rw-r--r--core/res/res/layout/screen_custom_title.xml1
-rw-r--r--core/res/res/values/attrs.xml8
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java363
16 files changed, 621 insertions, 454 deletions
diff --git a/api/current.txt b/api/current.txt
index 8340265..5cf7e48 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -345,7 +345,7 @@ package android {
field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
field public static final deprecated int capitalize = 16843113; // 0x1010169
- field public static final int castsShadow = 16843777; // 0x1010401
+ field public static final int castsShadow = 16843775; // 0x10103ff
field public static final int category = 16843752; // 0x10103e8
field public static final int centerBright = 16842956; // 0x10100cc
field public static final int centerColor = 16843275; // 0x101020b
@@ -542,7 +542,6 @@ package android {
field public static final int fromAlpha = 16843210; // 0x10101ca
field public static final int fromDegrees = 16843187; // 0x10101b3
field public static final int fromScene = 16843741; // 0x10103dd
- field public static final int fromSceneName = 16843773; // 0x10103fd
field public static final int fromXDelta = 16843206; // 0x10101c6
field public static final int fromXScale = 16843202; // 0x10101c2
field public static final int fromYDelta = 16843208; // 0x10101c8
@@ -890,7 +889,7 @@ package android {
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
- field public static final int requiredForProfile = 16843778; // 0x1010402
+ field public static final int requiredForProfile = 16843776; // 0x1010400
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
field public static final int resizeMode = 16843619; // 0x1010363
@@ -961,7 +960,7 @@ package android {
field public static final int shadowRadius = 16843108; // 0x1010164
field public static final int shape = 16843162; // 0x101019a
field public static final int shareInterpolator = 16843195; // 0x10101bb
- field public static final int sharedElementName = 16843775; // 0x10103ff
+ field public static final int sharedElementName = 16843773; // 0x10103fd
field public static final int sharedUserId = 16842763; // 0x101000b
field public static final int sharedUserLabel = 16843361; // 0x1010261
field public static final int shouldDisableView = 16843246; // 0x10101ee
@@ -1145,7 +1144,6 @@ package android {
field public static final int toAlpha = 16843211; // 0x10101cb
field public static final int toDegrees = 16843188; // 0x10101b4
field public static final int toScene = 16843742; // 0x10103de
- field public static final int toSceneName = 16843774; // 0x10103fe
field public static final int toXDelta = 16843207; // 0x10101c7
field public static final int toXScale = 16843203; // 0x10101c3
field public static final int toYDelta = 16843209; // 0x10101c9
@@ -1161,7 +1159,7 @@ package android {
field public static final int transformPivotX = 16843552; // 0x1010320
field public static final int transformPivotY = 16843553; // 0x1010321
field public static final int transition = 16843743; // 0x10103df
- field public static final int transitionGroup = 16843776; // 0x1010400
+ field public static final int transitionGroup = 16843774; // 0x10103fe
field public static final int transitionOrdering = 16843744; // 0x10103e0
field public static final int translationX = 16843554; // 0x1010322
field public static final int translationY = 16843555; // 0x1010323
@@ -3041,7 +3039,6 @@ package android.app {
method public int getTaskId();
method public final java.lang.CharSequence getTitle();
method public final int getTitleColor();
- method public android.os.Bundle getTransitionArgs();
method public final int getVolumeControlStream();
method public android.view.Window getWindow();
method public android.view.WindowManager getWindowManager();
@@ -3063,6 +3060,8 @@ package android.app {
method public void onAttachFragment(android.app.Fragment);
method public void onAttachedToWindow();
method public void onBackPressed();
+ method public void onCaptureSharedElementEnd();
+ method public void onCaptureSharedElementStart(android.transition.Transition);
method protected void onChildTitleChanged(android.app.Activity, java.lang.CharSequence);
method public void onConfigurationChanged(android.content.res.Configuration);
method public void onContentChanged();
@@ -3137,7 +3136,6 @@ package android.app {
method public void setContentView(android.view.View);
method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
method public final void setDefaultKeyMode(int);
- method public void setEarlyBackgroundTransition(boolean);
method public final void setFeatureDrawable(int, android.graphics.drawable.Drawable);
method public final void setFeatureDrawableAlpha(int, int);
method public final void setFeatureDrawableResource(int, int);
@@ -3178,7 +3176,6 @@ package android.app {
method public boolean startNextMatchingActivity(android.content.Intent);
method public boolean startNextMatchingActivity(android.content.Intent, android.os.Bundle);
method public void startSearch(java.lang.String, boolean, android.os.Bundle, boolean);
- method protected void startSharedElementTransition(android.os.Bundle);
method public deprecated void stopManagingCursor(android.database.Cursor);
method public void takeKeyEvents(boolean);
method public void triggerSearch(java.lang.String, android.os.Bundle);
@@ -3349,7 +3346,8 @@ package android.app {
public class ActivityOptions {
method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
- method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.os.Bundle);
+ method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.view.View, java.lang.String);
+ method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.util.Pair<android.view.View, java.lang.String>...);
method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
method public android.os.Bundle toBundle();
method public void update(android.app.ActivityOptions);
@@ -26829,15 +26827,11 @@ package android.transition {
ctor public TransitionManager();
method public static void beginDelayedTransition(android.view.ViewGroup);
method public static void beginDelayedTransition(android.view.ViewGroup, android.transition.Transition);
- method public android.transition.Transition getNamedTransition(java.lang.String, android.transition.Scene);
- method public android.transition.Transition getNamedTransition(android.transition.Scene, java.lang.String);
- method public java.lang.String[] getTargetSceneNames(android.transition.Scene);
method public static void go(android.transition.Scene);
method public static void go(android.transition.Scene, android.transition.Transition);
+ method public void setExitTransition(android.transition.Scene, android.transition.Transition);
method public void setTransition(android.transition.Scene, android.transition.Transition);
method public void setTransition(android.transition.Scene, android.transition.Scene, android.transition.Transition);
- method public void setTransition(android.transition.Scene, java.lang.String, android.transition.Transition);
- method public void setTransition(java.lang.String, android.transition.Scene, android.transition.Transition);
method public void transitionTo(android.transition.Scene);
}
@@ -29808,6 +29802,7 @@ package android.view {
method public abstract boolean isFloating();
method public abstract boolean isShortcutKey(int, android.view.KeyEvent);
method public final void makeActive();
+ method public void mapTransitionTargets(java.util.Map<java.lang.String, java.lang.String>);
method protected abstract void onActive();
method public abstract void onConfigurationChanged(android.content.res.Configuration);
method public abstract void openPanel(int, android.view.KeyEvent);
@@ -29846,6 +29841,7 @@ package android.view {
method public abstract void setTitle(java.lang.CharSequence);
method public abstract deprecated void setTitleColor(int);
method public void setTransitionManager(android.transition.TransitionManager);
+ method public void setTriggerEarlyEnterTransition(boolean);
method public void setType(int);
method public void setUiOptions(int);
method public void setUiOptions(int, int);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 9a3c290..3297fe0 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -18,6 +18,7 @@ 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;
@@ -3316,7 +3317,7 @@ public class Activity extends ContextThemeWrapper
@Nullable Bundle appSearchData, boolean globalSearch) {
ensureSearchManager();
mSearchManager.startSearch(initialQuery, selectInitialQuery, getComponentName(),
- appSearchData, globalSearch);
+ appSearchData, globalSearch);
}
/**
@@ -3446,7 +3447,11 @@ public class Activity extends ContextThemeWrapper
* @see #startActivity
*/
public void startActivityForResult(Intent intent, int requestCode) {
- startActivityForResult(intent, requestCode, null);
+ Bundle options = null;
+ if (mWindow.hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
+ options = ActivityOptions.makeSceneTransitionAnimation(null).toBundle();
+ }
+ startActivityForResult(intent, requestCode, options);
}
/**
@@ -3484,12 +3489,15 @@ public class Activity extends ContextThemeWrapper
* @see #startActivity
*/
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
- TransitionManager tm = getContentTransitionManager();
- if (tm != null && options != null) {
+ if (options != null) {
ActivityOptions activityOptions = new ActivityOptions(options);
if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
- getWindow().startExitTransition(activityOptions);
- options = activityOptions.toBundle();
+ if (mActionBar != null) {
+ ArrayMap<String, View> sharedElementMap = new ArrayMap<String, View>();
+ mActionBar.captureSharedElements(sharedElementMap);
+ activityOptions.addSharedElements(sharedElementMap);
+ }
+ options = mWindow.startExitTransition(activityOptions);
}
}
if (mParent == null) {
@@ -3664,7 +3672,7 @@ public class Activity extends ContextThemeWrapper
*/
@Override
public void startActivity(Intent intent) {
- startActivity(intent, null);
+ this.startActivity(intent, null);
}
/**
@@ -4720,7 +4728,8 @@ public class Activity extends ContextThemeWrapper
*/
public final void setProgressBarIndeterminate(boolean indeterminate) {
getWindow().setFeatureInt(Window.FEATURE_PROGRESS,
- indeterminate ? Window.PROGRESS_INDETERMINATE_ON : Window.PROGRESS_INDETERMINATE_OFF);
+ indeterminate ? Window.PROGRESS_INDETERMINATE_ON
+ : Window.PROGRESS_INDETERMINATE_OFF);
}
/**
@@ -5330,12 +5339,6 @@ public class Activity extends ContextThemeWrapper
mTransitionActivityOptions = activityOptions;
sceneTransitionListener = new Window.SceneTransitionListener() {
@Override
- public void enterSharedElement(Bundle transitionArgs) {
- startSharedElementTransition(transitionArgs);
- mTransitionActivityOptions = null;
- }
-
- @Override
public void nullPendingTransition() {
overridePendingTransition(0, 0);
}
@@ -5349,6 +5352,16 @@ public class Activity extends ContextThemeWrapper
public void convertToTranslucent() {
Activity.this.convertToTranslucent(null);
}
+
+ @Override
+ public void sharedElementStart(Transition transition) {
+ Activity.this.onCaptureSharedElementStart(transition);
+ }
+
+ @Override
+ public void sharedElementEnd() {
+ Activity.this.onCaptureSharedElementEnd();
+ }
};
}
@@ -5542,53 +5555,23 @@ public class Activity extends ContextThemeWrapper
}
/**
- * Gets the entering Activity transition args. Will be null if
- * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)} was
- * not used to pass a Bundle to startActivity. The Bundle passed to that method in the
- * calling Activity is returned here.
- * <p>After startSharedElementTransition is called, this method will return null.</p>
+ * 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.
*
- * @return The Bundle passed into Bundle parameter of
- * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)}
- * in the calling Activity.
+ * @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 Bundle getTransitionArgs() {
- if (mTransitionActivityOptions == null) {
- return null;
- }
- return mTransitionActivityOptions.getSceneTransitionArgs();
+ public void onCaptureSharedElementStart(Transition transition) {
}
/**
- * Override to transfer a shared element from a calling Activity to this Activity.
- * Shared elements will be made VISIBLE before this call. The Activity is responsible
- * for transitioning the shared elements from their location to the eventual destination.
- * The shared element will be laid out a the destination when this method is called.
- *
- * @param transitionArgs The same as returned from {@link #getTransitionArgs()}, this should
- * contain information from the calling Activity to tell where the
- * shared element should be placed.
+ * 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.
*/
- protected void startSharedElementTransition(Bundle transitionArgs) {
- }
-
- /**
- * Controls how the background fade is triggered when there is an entering Activity transition.
- * If fadeEarly is true, the Window background will fade in as soon as the shared elements are
- * ready to switch. If fadeEarly is false, the background will fade only after the calling
- * Activity's exit transition completes. By default, the Window will fade in when the calling
- * Activity's exit transition completes.
- *
- * @param fadeEarly Set to true to fade out the exiting Activity as soon as the shared elements
- * are transferred. Set to false to fade out the exiting Activity as soon as
- * the shared element is transferred.
- * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
- */
- public void setEarlyBackgroundTransition(boolean fadeEarly) {
- if (mTransitionActivityOptions == null) {
- return;
- }
- mWindow.setEarlyBackgroundTransition(fadeEarly);
+ public void onCaptureSharedElementEnd() {
}
/**
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 3f97c40..07247ff 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -16,7 +16,6 @@
package android.app;
-import android.animation.Animator;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
@@ -24,8 +23,8 @@ import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.transition.Transition;
-import android.util.ArrayMap;
import android.util.Log;
+import android.util.Pair;
import android.view.View;
import java.util.ArrayList;
@@ -100,12 +99,6 @@ public class ActivityOptions {
public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
/**
- * Arguments for the scene transition about to begin.
- * @hide
- */
- public static final String KEY_SCENE_TRANSITION_ARGS = "android:sceneTransitionArgs";
-
- /**
* For Activity transitions, the calling Activity's TransitionListener used to
* notify the called Activity when the shared element and the exit transitions
* complete.
@@ -120,9 +113,15 @@ public class ActivityOptions {
private static final String KEY_TRANSITION_TARGET_LISTENER = "android:transitionTargetListener";
/**
- * The shared element's texture ID (TODO: not used yet).
+ * 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_TEXTURE_ID = "android:sharedElementTextureId";
+ 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;
@@ -146,9 +145,10 @@ public class ActivityOptions {
private int mStartY;
private int mStartWidth;
private int mStartHeight;
- private Bundle mTransitionArgs;
private IRemoteCallback mAnimationStartedListener;
private IRemoteCallback mTransitionCompleteListener;
+ private ArrayList<String> mSharedElementNames;
+ private ArrayList<String> mLocalElementNames;
/**
* Create an ActivityOptions specifying a custom animation to run when
@@ -226,7 +226,7 @@ public class ActivityOptions {
/** @hide */
public interface ActivityTransitionTarget {
- void sharedElementTransitionComplete();
+ void sharedElementTransitionComplete(Bundle transitionArgs);
void exitTransitionComplete();
}
@@ -348,35 +348,51 @@ public class ActivityOptions {
}
/**
- * Create an ActivityOptions to transition between Activities using cross-Activity animation.
- * When visual elements are to carry between Activities, args should be used to tell the called
- * Activity about the location and size.
- *
- * TODO: Provide facility to capture layout and bitmap of shared elements.
- *
- * <p>When
- * {@link android.app.Activity#startActivities(android.content.Intent[], android.os.Bundle)}
- * is used with the {@link #toBundle()} result, the Activity's content scene will automatically
- * transition out by setting their visibility to {@link View#INVISIBLE}. Shared elements
- * ({@link android.view.View#setSharedElementName(String)}) are unmodified during the
- * transition to allow the started Activity to seamlessly take it over. ViewGroups typically
- * don't transition out, and instead transition out their children unless they have a
- * background. To modify this behavior, use
- * {@link android.view.ViewGroup#setTransitionGroup(boolean)}.</p>
+ * 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.
*
* <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 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.
+ */
+ public static ActivityOptions makeSceneTransitionAnimation(View sharedElement,
+ String sharedElementName) {
+ return makeSceneTransitionAnimation(
+ new Pair<View, String>(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.
*
- * @param args Contains information for transferring a view between this Activity and the
- * target Activity. Will be used by the called Activity to transition the
- * view to its eventual destination
- * @see android.app.Activity#startSharedElementTransition(android.os.Bundle)
+ * <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.
+ * @return Returns a new ActivityOptions object that you can use to
+ * supply these options as the options Bundle when starting an activity.
*/
- public static ActivityOptions makeSceneTransitionAnimation(Bundle args) {
+ public static ActivityOptions makeSceneTransitionAnimation(
+ Pair<View, String>... sharedElements) {
ActivityOptions opts = new ActivityOptions();
opts.mAnimationType = ANIM_SCENE_TRANSITION;
- opts.mTransitionArgs = args;
+ 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);
+ }
+ }
return opts;
}
@@ -412,9 +428,10 @@ public class ActivityOptions {
break;
case ANIM_SCENE_TRANSITION:
- mTransitionArgs = opts.getBundle(KEY_SCENE_TRANSITION_ARGS);
mTransitionCompleteListener = IRemoteCallback.Stub.asInterface(
opts.getBinder(KEY_TRANSITION_COMPLETE_LISTENER));
+ mSharedElementNames = opts.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
+ mLocalElementNames = opts.getStringArrayList(KEY_LOCAL_ELEMENT_NAMES);
break;
}
}
@@ -465,17 +482,19 @@ public class ActivityOptions {
}
/** @hide */
- public Bundle getSceneTransitionArgs() {
- return mTransitionArgs;
- }
-
- /** @hide */
public IRemoteCallback getOnAnimationStartListener() {
return mAnimationStartedListener;
}
/** @hide */
- public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target) {
+ public ArrayList<String> getSharedElementNames() { return mSharedElementNames; }
+
+ /** @hide */
+ public ArrayList<String> getLocalElementNames() { return mLocalElementNames; }
+
+ /** @hide */
+ public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target,
+ ArrayList<String> sharedElementNames) {
boolean listenerSent = false;
if (mTransitionCompleteListener != null) {
IRemoteCallback callback = new IRemoteCallback.Stub() {
@@ -484,13 +503,13 @@ public class ActivityOptions {
if (data == null) {
target.exitTransitionComplete();
} else {
- // TODO: Use texture id
- target.sharedElementTransitionComplete();
+ target.sharedElementTransitionComplete(data);
}
}
};
Bundle bundle = new Bundle();
bundle.putBinder(KEY_TRANSITION_TARGET_LISTENER, callback.asBinder());
+ bundle.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, sharedElementNames);
try {
mTransitionCompleteListener.sendResult(bundle);
listenerSent = true;
@@ -499,12 +518,23 @@ public class ActivityOptions {
}
}
if (!listenerSent) {
- target.sharedElementTransitionComplete();
+ target.sharedElementTransitionComplete(null);
target.exitTransitionComplete();
}
}
/** @hide */
+ public void dispatchSharedElementsReady() {
+ if (mTransitionCompleteListener != null) {
+ try {
+ mTransitionCompleteListener.sendResult(null);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Couldn't synchronize shared elements", e);
+ }
+ }
+ }
+
+ /** @hide */
public void abort() {
if (mAnimationStartedListener != null) {
try {
@@ -530,6 +560,8 @@ public class ActivityOptions {
if (otherOptions.mPackageName != null) {
mPackageName = otherOptions.mPackageName;
}
+ mSharedElementNames = null;
+ mLocalElementNames = null;
switch (otherOptions.mAnimationType) {
case ANIM_CUSTOM:
mAnimationType = otherOptions.mAnimationType;
@@ -544,7 +576,6 @@ public class ActivityOptions {
}
mAnimationStartedListener = otherOptions.mAnimationStartedListener;
mTransitionCompleteListener = null;
- mTransitionArgs = null;
break;
case ANIM_SCALE_UP:
mAnimationType = otherOptions.mAnimationType;
@@ -560,7 +591,6 @@ public class ActivityOptions {
}
mAnimationStartedListener = null;
mTransitionCompleteListener = null;
- mTransitionArgs = null;
break;
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
@@ -576,14 +606,14 @@ public class ActivityOptions {
}
mAnimationStartedListener = otherOptions.mAnimationStartedListener;
mTransitionCompleteListener = null;
- mTransitionArgs = null;
break;
case ANIM_SCENE_TRANSITION:
mAnimationType = otherOptions.mAnimationType;
mTransitionCompleteListener = otherOptions.mTransitionCompleteListener;
- mTransitionArgs = otherOptions.mTransitionArgs;
mThumbnail = null;
mAnimationStartedListener = null;
+ mSharedElementNames = otherOptions.mSharedElementNames;
+ mLocalElementNames = otherOptions.mLocalElementNames;
break;
}
}
@@ -627,11 +657,12 @@ public class ActivityOptions {
break;
case ANIM_SCENE_TRANSITION:
b.putInt(KEY_ANIM_TYPE, mAnimationType);
- b.putBundle(KEY_SCENE_TRANSITION_ARGS, mTransitionArgs);
if (mTransitionCompleteListener != null) {
b.putBinder(KEY_TRANSITION_COMPLETE_LISTENER,
mTransitionCompleteListener.asBinder());
}
+ b.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, mSharedElementNames);
+ b.putStringArrayList(KEY_LOCAL_ELEMENT_NAMES, mLocalElementNames);
break;
}
return b;
@@ -652,32 +683,52 @@ public class ActivityOptions {
}
/** @hide */
- public interface SharedElementSource {
- int getTextureId();
+ public void addSharedElements(Map<String, View> sharedElements) {
+ for (Map.Entry<String, View> entry : sharedElements.entrySet()) {
+ addSharedElement(entry.getValue(), entry.getKey());
+ }
}
- /**
- * In the calling Activity when transitioning out, sets the Transition to listen for
- * changes.
- * @hide
- */
- public void setExitTransition(Transition transition, SharedElementSource sharedElementSource) {
- mTransitionCompleteListener = new ExitTransitionListener(transition, sharedElementSource);
+ /** @hide */
+ public void updateSceneTransitionAnimation(Transition exitTransition,
+ Transition sharedElementTransition, SharedElementSource sharedElementSource) {
+ mTransitionCompleteListener = new ExitTransitionListener(exitTransition,
+ sharedElementTransition, sharedElementSource);
+ }
+
+ 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();
}
private static class ExitTransitionListener extends IRemoteCallback.Stub
- implements Transition.TransitionListener, Animator.AnimatorListener {
- private ArrayList<Animator> mSharedElementAnimators = new ArrayList<Animator>();
+ implements Transition.TransitionListener {
private boolean mSharedElementNotified;
private Transition mExitTransition;
+ private Transition mSharedElementTransition;
private IRemoteCallback mTransitionCompleteCallback;
private boolean mExitComplete;
+ private boolean mSharedElementComplete;
private SharedElementSource mSharedElementSource;
- public ExitTransitionListener(Transition transition, SharedElementSource sharedElementSource) {
+ public ExitTransitionListener(Transition exitTransition, Transition sharedElementTransition,
+ SharedElementSource sharedElementSource) {
mSharedElementSource = sharedElementSource;
- mExitTransition = transition;
+ mExitTransition = exitTransition;
mExitTransition.addListener(this);
+ mSharedElementTransition = sharedElementTransition;
+ mSharedElementTransition.addListener(this);
}
@Override
@@ -685,36 +736,36 @@ public class ActivityOptions {
if (data != null) {
mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface(
data.getBinder(KEY_TRANSITION_TARGET_LISTENER));
+ ArrayList<String> sharedElementNames
+ = data.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
+ mSharedElementSource.acceptedSharedElements(sharedElementNames);
notifySharedElement();
notifyExit();
+ } else {
+ mSharedElementSource.hideSharedElements();
}
}
@Override
public void onTransitionStart(Transition transition) {
- ArrayMap<Animator, Transition.AnimationInfo> runningAnimators
- = Transition.getRunningAnimators();
- for (Map.Entry<Animator, Transition.AnimationInfo> entry : runningAnimators.entrySet()) {
- if (entry.getValue().view.getSharedElementName() != null) {
- mSharedElementAnimators.add(entry.getKey());
- entry.getKey().addListener(this);
- }
- }
- notifySharedElement();
}
@Override
public void onTransitionEnd(Transition transition) {
- mExitComplete = true;
- notifyExit();
- mExitTransition.removeListener(this);
+ if (transition == mExitTransition) {
+ mExitComplete = true;
+ notifyExit();
+ mExitTransition.removeListener(this);
+ } else {
+ mSharedElementComplete = true;
+ notifySharedElement();
+ mSharedElementTransition.removeListener(this);
+ }
}
@Override
public void onTransitionCancel(Transition transition) {
- mExitComplete = true;
- notifyExit();
- mExitTransition.removeListener(this);
+ onTransitionEnd(transition);
}
@Override
@@ -725,34 +776,13 @@ public class ActivityOptions {
public void onTransitionResume(Transition transition) {
}
- @Override
- public void onAnimationStart(Animator animation) {
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- mSharedElementAnimators.remove(animation);
- notifySharedElement();
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mSharedElementAnimators.remove(animation);
- notifySharedElement();
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- }
-
private void notifySharedElement() {
- if (!mSharedElementNotified && mSharedElementAnimators.isEmpty()
+ if (!mSharedElementNotified && mSharedElementComplete
&& mTransitionCompleteCallback != null) {
mSharedElementNotified = true;
try {
- Bundle bundle = new Bundle();
- bundle.putInt(KEY_SHARED_ELEMENT_TEXTURE_ID, mSharedElementSource.getTextureId());
- mTransitionCompleteCallback.sendResult(bundle);
+ Bundle sharedElementState = mSharedElementSource.getSharedElementExitState();
+ mTransitionCompleteCallback.sendResult(sharedElementState);
} catch (RemoteException e) {
Log.w(TAG, "Couldn't notify that the transition ended", e);
}
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index fd3f9b3..9f1e72d 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -552,8 +552,7 @@ public abstract class Transition implements Cloneable {
return false;
}
- /** @hide */
- public static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
+ private static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
ArrayMap<Animator, AnimationInfo> runningAnimators = sRunningAnimators.get();
if (runningAnimators == null) {
runningAnimators = new ArrayMap<Animator, AnimationInfo>();
@@ -1113,30 +1112,32 @@ public abstract class Transition implements Cloneable {
}
}
}
- TransitionValues values = new TransitionValues();
- values.view = view;
- if (start) {
- captureStartValues(values);
- } else {
- captureEndValues(values);
- }
- if (start) {
- if (!isListViewItem) {
- mStartValues.viewValues.put(view, values);
- if (id >= 0) {
- mStartValues.idValues.put((int) id, values);
- }
+ if (view.getParent() instanceof ViewGroup) {
+ TransitionValues values = new TransitionValues();
+ values.view = view;
+ if (start) {
+ captureStartValues(values);
} else {
- mStartValues.itemIdValues.put(itemId, values);
+ captureEndValues(values);
}
- } else {
- if (!isListViewItem) {
- mEndValues.viewValues.put(view, values);
- if (id >= 0) {
- mEndValues.idValues.put((int) id, values);
+ if (start) {
+ if (!isListViewItem) {
+ mStartValues.viewValues.put(view, values);
+ if (id >= 0) {
+ mStartValues.idValues.put((int) id, values);
+ }
+ } else {
+ mStartValues.itemIdValues.put(itemId, values);
}
} else {
- mEndValues.itemIdValues.put(itemId, values);
+ if (!isListViewItem) {
+ mEndValues.viewValues.put(view, values);
+ if (id >= 0) {
+ mEndValues.idValues.put((int) id, values);
+ }
+ } else {
+ mEndValues.itemIdValues.put(itemId, values);
+ }
}
}
if (view instanceof ViewGroup) {
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 9fa554c..912f2ed 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -285,46 +285,27 @@ public class TransitionInflater {
com.android.internal.R.styleable.TransitionManager);
int transitionId = a.getResourceId(
com.android.internal.R.styleable.TransitionManager_transition, -1);
- Scene fromScene = null, toScene = null;
int fromId = a.getResourceId(
com.android.internal.R.styleable.TransitionManager_fromScene, -1);
- if (fromId >= 0) fromScene = Scene.getSceneForLayout(sceneRoot, fromId, mContext);
+ Scene fromScene = (fromId < 0) ? null: Scene.getSceneForLayout(sceneRoot, fromId, mContext);
int toId = a.getResourceId(
com.android.internal.R.styleable.TransitionManager_toScene, -1);
- if (toId >= 0) toScene = Scene.getSceneForLayout(sceneRoot, toId, mContext);
- String fromName = a.getString(
- com.android.internal.R.styleable.TransitionManager_fromSceneName);
- String toName = a.getString(
- com.android.internal.R.styleable.TransitionManager_toSceneName);
+ Scene toScene = (toId < 0) ? null : Scene.getSceneForLayout(sceneRoot, toId, mContext);
+
if (transitionId >= 0) {
Transition transition = inflateTransition(transitionId);
if (transition != null) {
- if (fromScene != null) {
- boolean hasDest = false;
- if (toScene != null) {
- transitionManager.setTransition(fromScene, toScene, transition);
- hasDest = true;
- }
-
- if (!TextUtils.isEmpty(toName)) {
- transitionManager.setTransition(fromScene, toName, transition);
- hasDest = true;
- }
-
- if (!hasDest) {
- throw new RuntimeException("No matching toScene or toSceneName for given " +
- "fromScene for transition ID " + transitionId);
- }
- } else if (toId >= 0) {
- transitionManager.setTransition(toScene, transition);
- }
- if (fromName != null) {
- if (toScene != null) {
- transitionManager.setTransition(fromName, toScene, transition);
- } else {
- throw new RuntimeException("No matching toScene for given fromSceneName " +
+ 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);
+ } else {
+ transitionManager.setTransition(fromScene, toScene, transition);
}
}
}
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 0106f7f..f3abfb0 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -70,12 +70,9 @@ 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>>();
- ArrayMap<Scene, ArrayMap<String, Transition>> mSceneNameTransitions =
- new ArrayMap<Scene, ArrayMap<String, Transition>>();
- ArrayMap<String, ArrayMap<Scene, Transition>> mNameSceneTransitions =
- new ArrayMap<String, ArrayMap<Scene, Transition>>();
private static ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>
sRunningTransitions =
new ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>();
@@ -122,6 +119,21 @@ public class TransitionManager {
}
/**
+ * 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.
*
@@ -169,6 +181,9 @@ public class TransitionManager {
}
}
transition = mSceneTransitions.get(scene);
+ if (transition == null && sceneRoot != null) {
+ transition = mExitSceneTransitions.get(Scene.getCurrentScene(sceneRoot));
+ }
return (transition != null) ? transition : sDefaultTransition;
}
@@ -224,138 +239,31 @@ public class TransitionManager {
}
/**
- * Retrieve the transition from a named scene to a target defined scene if one has been
+ * Retrieve the transition to a target defined scene if one has been
* associated with this TransitionManager.
*
- * <p>A named scene is an indirect link for a transition. Fundamentally a named
- * scene represents a potentially arbitrary intersection point of two otherwise independent
- * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
- * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
- * In this way applications may define an API for more sophisticated transitions between
- * caller and called activities very similar to the way that <code>Intent</code> extras
- * define APIs for arguments and data propagation between activities.</p>
- *
- * @param fromName Named scene that this transition corresponds to
* @param toScene Target scene that this transition will move to
- * @return Transition corresponding to the given fromName and toScene or null
+ * @return Transition corresponding to the given toScene or null
* if no association exists in this TransitionManager
*
- * @see #setTransition(String, Scene, Transition)
+ * @see #setTransition(Scene, Transition)
+ * @hide
*/
- public Transition getNamedTransition(String fromName, Scene toScene) {
- ArrayMap<Scene, Transition> m = mNameSceneTransitions.get(fromName);
- if (m != null) {
- return m.get(toScene);
- }
- return null;
+ 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.
*
- * <p>A named scene is an indirect link for a transition. Fundamentally a named
- * scene represents a potentially arbitrary intersection point of two otherwise independent
- * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
- * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
- * In this way applications may define an API for more sophisticated transitions between
- * caller and called activities very similar to the way that <code>Intent</code> extras
- * define APIs for arguments and data propagation between activities.</p>
- *
* @param fromScene Scene that this transition starts from
- * @param toName Name of the target scene
- * @return Transition corresponding to the given fromScene and toName or null
+ * @return Transition corresponding to the given fromScene or null
* if no association exists in this TransitionManager
+ * @hide
*/
- public Transition getNamedTransition(Scene fromScene, String toName) {
- ArrayMap<String, Transition> m = mSceneNameTransitions.get(fromScene);
- if (m != null) {
- return m.get(toName);
- }
- return null;
- }
-
- /**
- * Retrieve the supported target named scenes when transitioning away from the given scene.
- *
- * <p>A named scene is an indirect link for a transition. Fundamentally a named
- * scene represents a potentially arbitrary intersection point of two otherwise independent
- * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
- * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
- * In this way applications may define an API for more sophisticated transitions between
- * caller and called activities very similar to the way that <code>Intent</code> extras
- * define APIs for arguments and data propagation between activities.</p>
- *
- * @param fromScene Scene to transition from
- * @return An array of Strings naming each supported transition starting from
- * <code>fromScene</code>. If no transitions to a named scene from the given
- * scene are supported this function will return a String[] of length 0.
- *
- * @see #setTransition(Scene, String, Transition)
- */
- public String[] getTargetSceneNames(Scene fromScene) {
- final ArrayMap<String, Transition> m = mSceneNameTransitions.get(fromScene);
- if (m == null) {
- return EMPTY_STRINGS;
- }
- final int count = m.size();
- final String[] result = new String[count];
- for (int i = 0; i < count; i++) {
- result[i] = m.keyAt(i);
- }
- return result;
- }
-
- /**
- * Set a transition from a specific scene to a named scene.
- *
- * <p>A named scene is an indirect link for a transition. Fundamentally a named
- * scene represents a potentially arbitrary intersection point of two otherwise independent
- * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
- * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
- * In this way applications may define an API for more sophisticated transitions between
- * caller and called activities very similar to the way that <code>Intent</code> extras
- * define APIs for arguments and data propagation between activities.</p>
- *
- * @param fromScene Scene to transition from
- * @param toName Named scene to transition to
- * @param transition Transition to use
- *
- * @see #getTargetSceneNames(Scene)
- */
- public void setTransition(Scene fromScene, String toName, Transition transition) {
- ArrayMap<String, Transition> m = mSceneNameTransitions.get(fromScene);
- if (m == null) {
- m = new ArrayMap<String, Transition>();
- mSceneNameTransitions.put(fromScene, m);
- }
- m.put(toName, transition);
- }
-
- /**
- * Set a transition from a named scene to a concrete scene.
- *
- * <p>A named scene is an indirect link for a transition. Fundamentally a named
- * scene represents a potentially arbitrary intersection point of two otherwise independent
- * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
- * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
- * In this way applications may define an API for more sophisticated transitions between
- * caller and called activities very similar to the way that <code>Intent</code> extras
- * define APIs for arguments and data propagation between activities.</p>
- *
- * @param fromName Named scene to transition from
- * @param toScene Scene to transition to
- * @param transition Transition to use
- *
- * @see #getNamedTransition(String, Scene)
- */
- public void setTransition(String fromName, Scene toScene, Transition transition) {
- ArrayMap<Scene, Transition> m = mNameSceneTransitions.get(fromName);
- if (m == null) {
- m = new ArrayMap<Scene, Transition>();
- mNameSceneTransitions.put(fromName, m);
- }
- m.put(toScene, transition);
+ public Transition getExitTransition(Scene fromScene) {
+ return mExitSceneTransitions.get(fromScene);
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e9082c3..99aee29 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -101,7 +101,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
@@ -18842,6 +18844,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
+ /**
+ * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
+ * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
+ * a normal View or a ViewGroup with
+ * {@link android.view.ViewGroup#isTransitionGroup()} true.
+ * @hide
+ */
+ public void captureTransitioningViews(List<View> transitioningViews) {
+ if (getVisibility() == View.VISIBLE) {
+ transitioningViews.add(this);
+ }
+ }
+
+ /**
+ * Adds all Views that have {@link #getSharedElementName()} non-null to sharedElements.
+ * @param sharedElements Will contain all Views in the hierarchy having a shared element name.
+ * @hide
+ */
+ public void findSharedElements(Map<String, View> sharedElements) {
+ if (getVisibility() == VISIBLE) {
+ String sharedElementName = getSharedElementName();
+ if (sharedElementName != null) {
+ sharedElements.put(sharedElementName, this);
+ }
+ }
+ }
+
//
// Properties
//
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9cd3c9d..cf5e8cf 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -31,6 +31,7 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Build;
+import android.os.Bundle;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -50,6 +51,8 @@ import com.android.internal.util.Predicate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
@@ -2300,14 +2303,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* individually during the transition.
* @return True if the ViewGroup should be acted on together during an Activity transition.
* The default value is false when the background is null and true when the background
- * is not null.
- * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
+ * is not null or if {@link #getSharedElementName()} is not null.
*/
public boolean isTransitionGroup() {
if ((mGroupFlags & FLAG_IS_TRANSITION_GROUP_SET) != 0) {
return ((mGroupFlags & FLAG_IS_TRANSITION_GROUP) != 0);
} else {
- return getBackground() != null;
+ return getBackground() != null || getSharedElementName() != null;
}
}
@@ -2318,7 +2320,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* 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.os.Bundle)
*/
public void setTransitionGroup(boolean isTransitionGroup) {
mGroupFlags |= FLAG_IS_TRANSITION_GROUP_SET;
@@ -5880,6 +5881,37 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
protected void onSetLayoutParams(View child, LayoutParams layoutParams) {
}
+ /** @hide */
+ @Override
+ public void captureTransitioningViews(List<View> transitioningViews) {
+ if (getVisibility() != View.VISIBLE) {
+ return;
+ }
+ if (isTransitionGroup()) {
+ transitioningViews.add(this);
+ } else {
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ View child = getChildAt(i);
+ child.captureTransitioningViews(transitioningViews);
+ }
+ }
+ }
+
+ /** @hide */
+ @Override
+ public void findSharedElements(Map<String, View> sharedElements) {
+ if (getVisibility() != VISIBLE) {
+ return;
+ }
+ super.findSharedElements(sharedElements);
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ View child = getChildAt(i);
+ child.findSharedElements(sharedElements);
+ }
+ }
+
/**
* LayoutParams are used by views to tell their parents how they want to be
* laid out. See
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 11740ab..24b8248 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -29,9 +29,12 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemProperties;
import android.transition.Scene;
+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
@@ -1386,30 +1389,43 @@ public abstract class Window {
* @hide
*/
public interface SceneTransitionListener {
- void enterSharedElement(Bundle transitionArgs);
void nullPendingTransition();
void convertFromTranslucent();
void convertToTranslucent();
+ void sharedElementStart(Transition transition);
+ void sharedElementEnd();
}
/**
- * Controls how the background fade is triggered. If fadeEarly is true, the Window background
- * will fade in as soon as the shared elements are ready to switch. If fadeEarly is false,
- * the background will fade only after the calling Activity's exit transition completes.
- * By default, the Window will fade in when the calling Activity's exit transition completes.
+ * Controls when the Activity enter scene is triggered and the background is faded in. If
+ * triggerEarly 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 triggerEarly is
+ * false, the Activity enter scene and background fade will be triggered when the calling
+ * Activity's exit transition completes.
*
- * @param fadeEarly Set to true to fade out the exiting Activity as soon as the shared elements
- * are transferred. Set to false to fade out the exiting Activity as soon as
- * the shared element is transferred.
- * @hide
+ * @param triggerEarly 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.
*/
- public void setEarlyBackgroundTransition(boolean fadeEarly) {
+ public void setTriggerEarlyEnterTransition(boolean triggerEarly) {
}
/**
* Start the exit transition.
* @hide
*/
- public void startExitTransition(ActivityOptions activityOptions) {
+ public Bundle startExitTransition(ActivityOptions options) {
+ 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.
+ */
+ public void mapTransitionTargets(Map<String, String> sharedElementNames) {
}
}
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 0a80495..cc51a8b 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -57,6 +57,7 @@ import android.widget.SpinnerAdapter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Map;
/**
* ActionBarImpl is the ActionBar implementation used
@@ -355,6 +356,10 @@ public class ActionBarImpl 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:
diff --git a/core/res/res/layout-xlarge/screen_action_bar.xml b/core/res/res/layout-xlarge/screen_action_bar.xml
index e495e53..d2fe9fa 100644
--- a/core/res/res/layout-xlarge/screen_action_bar.xml
+++ b/core/res/res/layout-xlarge/screen_action_bar.xml
@@ -34,6 +34,7 @@ the Action Bar enabled overlaying application content.
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
style="?android:attr/actionBarStyle"
+ android:sharedElementName="android:action_bar"
android:gravity="top">
<com.android.internal.widget.ActionBarView
android:id="@+id/action_bar"
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index b1889a2..7b9a20b 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -33,6 +33,7 @@ This is an optimized layout for a screen with the Action Bar enabled.
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
style="?android:attr/actionBarStyle"
+ android:sharedElementName="android:action_bar"
android:gravity="top">
<com.android.internal.widget.ActionBarView
android:id="@+id/action_bar"
diff --git a/core/res/res/layout/screen_custom_title.xml b/core/res/res/layout/screen_custom_title.xml
index e3364d1..d02cc8b 100644
--- a/core/res/res/layout/screen_custom_title.xml
+++ b/core/res/res/layout/screen_custom_title.xml
@@ -31,6 +31,7 @@ This is a custom layout for a screen.
<FrameLayout android:id="@android:id/title_container"
android:layout_width="match_parent"
android:layout_height="?android:attr/windowTitleSize"
+ android:sharedElementName="android:title"
style="?android:attr/windowTitleBackgroundStyle">
</FrameLayout>
<FrameLayout android:id="@android:id/content"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index bfd7565..1c5be42 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4760,14 +4760,6 @@
<attr name="fromScene" format="reference" />
<!-- The destination scene in this scene change. -->
<attr name="toScene" format="reference" />
- <!-- The name of the originating scene in this scene change.
- Apps should treat this name as an API in the same sense
- that an Intent action or extra key is. -->
- <attr name="fromSceneName" format="string" />
- <!-- The name of the destination scene in this scene change.
- Apps should treat this name as an API in the same sense
- that an Intent action or extra key is. -->
- <attr name="toSceneName" format="string" />
</declare-styleable>
<!-- ========================== -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c814d25..3106daa 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2103,8 +2103,6 @@
<public type="attr" name="controlY1" />
<public type="attr" name="controlX2" />
<public type="attr" name="controlY2" />
- <public type="attr" name="fromSceneName" />
- <public type="attr" name="toSceneName" />
<public type="attr" name="sharedElementName" />
<public type="attr" name="transitionGroup" />
<public type="attr" name="castsShadow" />
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index c73d90a..02a2680 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -29,6 +29,8 @@ import android.transition.Scene;
import android.transition.Transition;
import android.transition.TransitionInflater;
import android.transition.TransitionManager;
+import android.transition.TransitionSet;
+import android.util.ArrayMap;
import android.view.ViewConfiguration;
import com.android.internal.R;
@@ -105,6 +107,9 @@ import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
/**
* Android-specific Window.
@@ -120,6 +125,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private static final long MAX_TRANSITION_START_WAIT = 500;
private static final long MAX_TRANSITION_FINISH_WAIT = 1000;
+ 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";
+
/**
* Simple callback used by the context menu and its submenus. The options
* menu submenus do not use this (their behavior is more complex).
@@ -239,7 +251,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private ActivityOptions mActivityOptions;
private SceneTransitionListener mSceneTransitionListener;
- private boolean mFadeEarly = true;
+ private boolean mTriggerEarly = true;
+ private Map<String, String> mSharedElementsMap;
static class WindowManagerHolder {
static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
@@ -2562,6 +2575,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return super.fitSystemWindows(insets);
}
+ @Override
+ public boolean isTransitionGroup() {
+ return false;
+ }
+
private void updateStatusGuard(Rect insets) {
boolean showStatusGuard = false;
// Show the status guard when the non-overlay contextual action bar is showing
@@ -3988,81 +4006,217 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
@Override
- public void setEarlyBackgroundTransition(boolean fadeEarly) {
- mFadeEarly = fadeEarly;
+ public void setTriggerEarlyEnterTransition(boolean triggerEarly) {
+ mTriggerEarly = triggerEarly;
}
@Override
- public void startExitTransition(ActivityOptions activityOptions) {
- Transition transition = mTransitionManager.getNamedTransition(getContentScene(), "null");
+ public void mapTransitionTargets(Map<String, String> sharedElementNames) {
+ mSharedElementsMap = sharedElementNames;
+ }
+
+ @Override
+ public Bundle startExitTransition(ActivityOptions activityOptions) {
+ if (mContentScene == null) {
+ return null;
+ }
+ Transition transition = mTransitionManager.getExitTransition(mContentScene);
if (transition == null) {
- transition = TransitionManager.getDefaultTransition().clone();
+ return null;
+ }
+
+ ArrayMap<String, View> sharedElements = findSharedElements(activityOptions);
+
+ // Find exiting Views and shared elements
+ final ArrayList<View> transitioningViews = new ArrayList<View>();
+ mDecor.captureTransitioningViews(transitioningViews);
+ transitioningViews.removeAll(sharedElements.values());
+
+ Transition exitTransition = cloneAndSetTransitionTargets(transition,
+ transitioningViews, true);
+ Transition sharedElementTransition = cloneAndSetTransitionTargets(transition,
+ transitioningViews, false);
+
+ // transitionSet is the total exit transition, including hero animation.
+ TransitionSet transitionSet = new TransitionSet();
+ transitionSet.addTransition(exitTransition);
+ transitionSet.addTransition(sharedElementTransition);
+
+ updateExitActivityOptions(activityOptions, sharedElements,
+ sharedElementTransition, exitTransition);
+
+ // Start exiting the Views that need to exit
+ TransitionManager.beginDelayedTransition(mDecor, transitionSet);
+ setViewVisibility(transitioningViews, View.INVISIBLE);
+
+ return activityOptions.toBundle();
+ }
+
+ private ArrayMap<String, View> findSharedElements(ActivityOptions activityOptions) {
+ ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
+ mDecor.findSharedElements(sharedElements);
+ ArrayList<String> localNames = activityOptions.getLocalElementNames();
+ sharedElements.keySet().retainAll(localNames);
+
+ ArrayList<String> targetNames = activityOptions.getSharedElementNames();
+ for (int i = 0; i < localNames.size(); i++) {
+ String localName = localNames.get(i);
+ View sharedElement = sharedElements.remove(localName);
+ String targetName = targetNames.get(i);
+ sharedElements.put(targetName, sharedElement);
}
- activityOptions.setExitTransition(transition, new ActivityOptions.SharedElementSource() {
+ return sharedElements;
+ }
+
+ private void updateExitActivityOptions(ActivityOptions activityOptions,
+ final Map<String, View> sharedElements, Transition sharedElementTransition,
+ Transition exitTransition) {
+
+ // Schedule capturing of the shared element state
+ final Bundle sharedElementArgs = new Bundle();
+ captureTerminalSharedElementState(sharedElements, sharedElementArgs);
+
+ ActivityOptions.SharedElementSource sharedElementSource
+ = new ActivityOptions.SharedElementSource() {
@Override
- public int getTextureId() {
- // TODO: move shared elements to a layer and return the texture id
- recurseHideExitingSharedElements(mContentParent);
- return 0;
+ public Bundle getSharedElementExitState() {
+ return sharedElementArgs;
}
- });
- ViewGroup sceneRoot = getContentScene().getSceneRoot();
- TransitionManager.beginDelayedTransition(sceneRoot, transition);
- recurseExitNonSharedElements(mContentParent);
- }
- private static void recurseExitNonSharedElements(ViewGroup viewGroup) {
- int numChildren = viewGroup.getChildCount();
- for (int i = 0; i < numChildren; i++) {
- View child = viewGroup.getChildAt(i);
- if (child.getSharedElementName() != null || (child.getVisibility() != View.VISIBLE)) {
- continue;
+ @Override
+ public void acceptedSharedElements(ArrayList<String> sharedElementNames) {
+ if (sharedElementNames.size() == sharedElements.size()) {
+ return; // They were all accepted
+ }
+ Transition transition = mTransitionManager.getExitTransition(mContentScene).clone();
+ TransitionManager.beginDelayedTransition(mDecor, transition);
+ for (String name: sharedElements.keySet()) {
+ if (!sharedElementNames.contains(name)) {
+ sharedElements.get(name).setVisibility(View.INVISIBLE);
+ }
+ }
+ sharedElements.keySet().retainAll(sharedElementNames);
}
- if (child instanceof ViewGroup && !((ViewGroup)child).isTransitionGroup()) {
- recurseExitNonSharedElements((ViewGroup) child);
- } else {
- child.setVisibility(View.INVISIBLE);
+
+ @Override
+ public void hideSharedElements() {
+ if (sharedElements != null) {
+ setViewVisibility(sharedElements.values(), View.INVISIBLE);
+ }
}
- }
+ };
+
+ activityOptions.updateSceneTransitionAnimation(
+ exitTransition, sharedElementTransition, sharedElementSource);
}
- private static void recurseHideViews(ViewGroup viewGroup, ArrayList<View> nonSharedElements,
- ArrayList<View> sharedElements) {
- int numChildren = viewGroup.getChildCount();
- for (int i = 0; i < numChildren; i++) {
- View child = viewGroup.getChildAt(i);
- if (child.getVisibility() != View.VISIBLE) {
- continue;
+ private void captureTerminalSharedElementState(final Map<String, View> sharedElements,
+ final Bundle sharedElementArgs) {
+ mDecor.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mDecor.getViewTreeObserver().removeOnPreDrawListener(this);
+ int[] tempLoc = new int[2];
+ for (String name : sharedElements.keySet()) {
+ View sharedElement = sharedElements.get(name);
+ captureSharedElementState(sharedElement, name, sharedElementArgs, tempLoc);
+ }
+ return true;
}
- if (child.getSharedElementName() != null) {
- sharedElements.add(child);
- child.setVisibility(View.INVISIBLE);
- } else if (child instanceof ViewGroup && !((ViewGroup)child).isTransitionGroup()) {
- recurseHideViews((ViewGroup) child, nonSharedElements, sharedElements);
+ });
+ }
+
+ private static Transition cloneAndSetTransitionTargets(Transition transition,
+ List<View> views, boolean add) {
+ transition = transition.clone();
+ if (!transition.getTargetIds().isEmpty() || !transition.getTargets().isEmpty()) {
+ TransitionSet set = new TransitionSet();
+ set.addTransition(transition);
+ transition = set;
+ }
+ for (View view: views) {
+ if (add) {
+ transition.addTarget(view);
} else {
- nonSharedElements.add(child);
- child.setVisibility(View.INVISIBLE);
+ transition.excludeTarget(view, true);
}
}
+ return transition;
}
- private static void recurseHideExitingSharedElements(ViewGroup viewGroup) {
- int numChildren = viewGroup.getChildCount();
- for (int i = 0; i < numChildren; i++) {
- View child = viewGroup.getChildAt(i);
- if (child.getVisibility() != View.VISIBLE) {
- continue;
- }
- if (child.getSharedElementName() != null) {
- child.setVisibility(View.INVISIBLE);
- } else if (child instanceof ViewGroup) {
- ViewGroup childViewGroup = (ViewGroup) child;
- recurseHideExitingSharedElements(childViewGroup);
- }
+ private static void setViewVisibility(Collection<View> views, int visibility) {
+ for (View view : views) {
+ view.setVisibility(visibility);
}
}
/**
+ * 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;
+ }
+
+ int x = sharedElementBundle.getInt(KEY_SCREEN_X);
+ view.getLocationOnScreen(tempLoc);
+ int offsetX = x - tempLoc[0];
+ view.offsetLeftAndRight(offsetX);
+
+ int width = sharedElementBundle.getInt(KEY_WIDTH);
+ view.setRight(view.getLeft() + width);
+
+ int y = sharedElementBundle.getInt(KEY_SCREEN_Y);
+ int offsetY = y - tempLoc[1];
+ view.offsetTopAndBottom(offsetY);
+
+ int height = sharedElementBundle.getInt(KEY_HEIGHT);
+ view.setBottom(view.getTop() + height);
+
+ float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
+ view.setTranslationZ(z);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
* Provides code for handling the Activity transition entering scene.
* When the first scene is laid out (onPreDraw), it makes views invisible.
* It then starts the entering transition by making non-shared elements visible. When
@@ -4080,46 +4234,57 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private boolean mAllDone;
private Handler mHandler = new Handler();
private boolean mEnterTransitionStarted;
- private ArrayList<View> mSharedElements = new ArrayList<View>();
+ private ArrayMap<String, View> mSharedElementTargets = new ArrayMap<String, View>();
+ private ArrayList<View> mEnteringViews = new ArrayList<View>();
public EnterScene() {
mSceneTransitionListener.nullPendingTransition();
Drawable background = getDecorView().getBackground();
if (background != null) {
- setBackgroundDrawable(null);
background.setAlpha(0);
- setBackgroundDrawable(background);
+ mDecor.drawableChanged();
}
mSceneTransitionListener.convertToTranslucent();
}
@Override
public boolean onPreDraw() {
- ViewTreeObserver observer = mContentParent.getViewTreeObserver();
+ ViewTreeObserver observer = mDecor.getViewTreeObserver();
observer.removeOnPreDrawListener(this);
if (!mEnterTransitionStarted && mSceneTransitionListener != null) {
mEnterTransitionStarted = true;
- ArrayList<View> enteringViews = new ArrayList<View>();
- recurseHideViews(mContentParent, enteringViews, mSharedElements);
- Transition transition = getTransitionManager().getNamedTransition("null",
- mContentScene);
- if (transition == null) {
- transition = TransitionManager.getDefaultTransition().clone();
+ mDecor.captureTransitioningViews(mEnteringViews);
+ ArrayList<String> sharedElementNames = mActivityOptions.getSharedElementNames();
+ if (sharedElementNames != null) {
+ mDecor.findSharedElements(mSharedElementTargets);
+ if (mSharedElementsMap != null) {
+ for (Map.Entry<String, String> entry : mSharedElementsMap.entrySet()) {
+ View sharedElement = mSharedElementTargets.remove(entry.getValue());
+ if (sharedElement != null) {
+ mSharedElementTargets.put(entry.getKey(), sharedElement);
+ }
+ }
+ }
+ mSharedElementTargets.keySet().retainAll(sharedElementNames);
+ mEnteringViews.removeAll(mSharedElementTargets.values());
}
- TransitionManager.beginDelayedTransition(mContentParent, transition);
- for (View hidden : enteringViews) {
- hidden.setVisibility(View.VISIBLE);
+
+ setViewVisibility(mEnteringViews, View.INVISIBLE);
+ setViewVisibility(mSharedElementTargets.values(), View.INVISIBLE);
+ if (mTriggerEarly) {
+ beginEnterScene();
}
observer.addOnPreDrawListener(this);
} else {
mHandler.postDelayed(this, MAX_TRANSITION_START_WAIT);
- mActivityOptions.dispatchSceneTransitionStarted(this);
+ mActivityOptions.dispatchSceneTransitionStarted(this,
+ new ArrayList<String>(mSharedElementTargets.keySet()));
}
return true;
}
public void start() {
- ViewTreeObserver observer = mContentParent.getViewTreeObserver();
+ ViewTreeObserver observer = mDecor.getViewTreeObserver();
observer.addOnPreDrawListener(this);
}
@@ -4129,25 +4294,43 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
@Override
- public void sharedElementTransitionComplete() {
+ public void sharedElementTransitionComplete(Bundle transitionArgs) {
if (!mSharedElementReadyReceived) {
mSharedElementReadyReceived = true;
mHandler.removeCallbacks(this);
mHandler.postDelayed(this, MAX_TRANSITION_FINISH_WAIT);
- for (View sharedElement: mSharedElements) {
- sharedElement.setVisibility(View.VISIBLE);
- }
- mSharedElements.clear();
- mContentParent.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- mContentParent.getViewTreeObserver().removeOnPreDrawListener(this);
- mSceneTransitionListener.enterSharedElement(
- mActivityOptions.getSceneTransitionArgs());
- return false;
+ if (!mSharedElementTargets.isEmpty()) {
+ Transition transition = getTransitionManager().getEnterTransition(
+ mContentScene);
+ if (transition == null) {
+ transition = TransitionManager.getDefaultTransition();
+ }
+ transition = transition.clone();
+ if (transitionArgs == null) {
+ TransitionManager.beginDelayedTransition(mDecor, transition);
+ setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
+ } else {
+ int[] tempLoc = new int[2];
+ for (Map.Entry<String, View> entry: mSharedElementTargets.entrySet()) {
+ setSharedElementState(entry.getValue(), entry.getKey(), transitionArgs,
+ tempLoc);
+ }
+ setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
+ mSceneTransitionListener.sharedElementStart(transition);
+ mDecor.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mDecor.getViewTreeObserver().removeOnPreDrawListener(this);
+ mSceneTransitionListener.sharedElementEnd();
+ mActivityOptions.dispatchSharedElementsReady();
+ return true;
+ }
+ });
+ TransitionManager.beginDelayedTransition(mDecor, transition);
}
- });
- if (mFadeEarly) {
+ }
+ if (mTriggerEarly) {
fadeInBackground();
}
}
@@ -4170,9 +4353,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return;
}
mAllDone = true;
- sharedElementTransitionComplete();
+ sharedElementTransitionComplete(null);
mHandler.removeCallbacks(this);
- if (!mFadeEarly) {
+ if (!mTriggerEarly) {
+ beginEnterScene();
fadeInBackground();
}
}
@@ -4193,5 +4377,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
@Override
public void onAnimationRepeat(Animator animation) {
}
+
+ private void beginEnterScene() {
+ Transition transition = getTransitionManager().getEnterTransition(mContentScene);
+ if (transition == null) {
+ transition = TransitionManager.getDefaultTransition().clone();
+ }
+ TransitionManager.beginDelayedTransition(mDecor, transition);
+ setViewVisibility(mEnteringViews, View.VISIBLE);
+ }
}
}