From 800d72b0e05049e4a8f90ea96ec165fc975264ce Mon Sep 17 00:00:00 2001 From: George Mount Date: Mon, 19 May 2014 07:09:00 -0700 Subject: [PATCH] Add to activity transition API as requested by consumers. Change-Id: Iae01d7560770bab0ff9a1728d6552b98b17108ce --- api/current.txt | 6 +- core/java/android/app/Activity.java | 32 ++++++++--- .../app/ActivityTransitionCoordinator.java | 21 ++++++- .../app/EnterTransitionCoordinator.java | 19 +++---- .../app/ExitTransitionCoordinator.java | 19 ++----- .../android/app/SharedElementListener.java | 57 ++++++++++++++----- core/res/res/values/ids.xml | 1 - core/res/res/values/public.xml | 1 - 8 files changed, 102 insertions(+), 54 deletions(-) diff --git a/api/current.txt b/api/current.txt index 6386ff2d213dd..17e26a5858b94 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1641,7 +1641,6 @@ package android { field public static final int selectAll = 16908319; // 0x102001f field public static final int selectTextMode = 16908333; // 0x102002d field public static final int selectedIcon = 16908302; // 0x102000e - field public static final int shared_element = 16908354; // 0x1020042 field public static final int startSelectingText = 16908328; // 0x1020028 field public static final int stopSelectingText = 16908329; // 0x1020029 field public static final int summary = 16908304; // 0x1020010 @@ -3337,6 +3336,8 @@ 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 setEnterSharedElementListener(android.app.SharedElementListener); + method public void setExitSharedElementListener(android.app.SharedElementListener); method public final void setFeatureDrawable(int, android.graphics.drawable.Drawable); method public final void setFeatureDrawableAlpha(int, int); method public final void setFeatureDrawableResource(int, int); @@ -3352,7 +3353,6 @@ package android.app { method public final void setResult(int); method public final void setResult(int, android.content.Intent); method public final void setSecondaryProgress(int); - method public void setSharedElementListener(android.app.SharedElementListener); method public void setTaskDescription(android.app.ActivityManager.TaskDescription); method public void setTitle(java.lang.CharSequence); method public void setTitle(int); @@ -4811,7 +4811,7 @@ package android.app { field public static final int START_STICKY_COMPATIBILITY = 0; // 0x0 } - public class SharedElementListener { + public abstract class SharedElementListener { ctor public SharedElementListener(); method public void handleRejectedSharedElements(java.util.List); method public void remapSharedElements(java.util.List, java.util.Map); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index e1a94d73f7357..3de971c2203b5 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -779,7 +779,8 @@ public class Activity extends ContextThemeWrapper final Handler mHandler = new Handler(); private ActivityTransitionState mActivityTransitionState = new ActivityTransitionState(); - SharedElementListener mTransitionListener = new SharedElementListener(); + SharedElementListener mEnterTransitionListener = SharedElementListener.NULL_LISTENER; + SharedElementListener mExitTransitionListener = SharedElementListener.NULL_LISTENER; /** Return the intent that started this activity. */ public Intent getIntent() { @@ -5557,16 +5558,32 @@ public class Activity extends ContextThemeWrapper /** * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, * android.view.View, String)} was used to start an Activity, listener - * will be called to handle shared elements. This requires + * will be called to handle shared elements on the launched Activity. This requires * {@link Window#FEATURE_CONTENT_TRANSITIONS}. * - * @param listener Used to manipulate how shared element transitions function. + * @param listener Used to manipulate shared element transitions on the launched Activity. */ - public void setSharedElementListener(SharedElementListener listener) { + public void setEnterSharedElementListener(SharedElementListener listener) { if (listener == null) { - listener = new SharedElementListener(); + listener = SharedElementListener.NULL_LISTENER; } - mTransitionListener = listener; + mEnterTransitionListener = listener; + } + + /** + * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, + * android.view.View, String)} was used to start an Activity, listener + * will be called to handle shared elements on the launching Activity. Most + * calls will only come when returning from the started Activity. + * This requires {@link Window#FEATURE_CONTENT_TRANSITIONS}. + * + * @param listener Used to manipulate shared element transitions on the launching Activity. + */ + public void setExitSharedElementListener(SharedElementListener listener) { + if (listener == null) { + listener = SharedElementListener.NULL_LISTENER; + } + mExitTransitionListener = listener; } // ------------------ Internal API ------------------ @@ -5882,7 +5899,8 @@ public class Activity extends ContextThemeWrapper * have completed drawing. This is necessary only after an {@link Activity} has been made * opaque using {@link Activity#convertFromTranslucent()} and before it has been drawn * translucent again following a call to {@link - * Activity#convertToTranslucent(TranslucentConversionListener)}. + * Activity#convertToTranslucent(android.app.Activity.TranslucentConversionListener, + * ActivityOptions)} * * @hide */ diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index 6c6a52fa51e37..2acf5b240a42d 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -189,15 +189,17 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { final protected SharedElementListener mListener; protected ResultReceiver mResultReceiver; final private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback(); + final protected boolean mIsReturning; public ActivityTransitionCoordinator(Window window, ArrayList allSharedElementNames, ArrayList accepted, ArrayList localNames, - SharedElementListener listener) { + SharedElementListener listener, boolean isReturning) { super(new Handler()); mWindow = window; mListener = listener; mAllSharedElementNames = allSharedElementNames; + mIsReturning = isReturning; setSharedElements(accepted, localNames); if (getViewsTransition() != null) { getDecor().captureTransitioningViews(mTransitioningViews); @@ -330,7 +332,21 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { mResultReceiver = resultReceiver; } - protected abstract Transition getViewsTransition(); + protected Transition getViewsTransition() { + if (mIsReturning) { + return getWindow().getExitTransition(); + } else { + return getWindow().getEnterTransition(); + } + } + + protected Transition getSharedElementTransition() { + if (mIsReturning) { + return getWindow().getSharedElementExitTransition(); + } else { + return getWindow().getSharedElementEnterTransition(); + } + } private static class FixedEpicenterCallback extends Transition.EpicenterCallback { private Rect mEpicenter; @@ -342,4 +358,5 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { return mEpicenter; } } + } diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index 636205bd5a652..b40d16c89efee 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -51,7 +51,6 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { private static final long MAX_WAIT_MS = 1500; private boolean mSharedElementTransitionStarted; - private boolean mIsReturning; private Activity mActivity; private boolean mHasStopped; private Handler mHandler; @@ -61,9 +60,8 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { ArrayList sharedElementNames, ArrayList acceptedNames, ArrayList mappedNames) { super(activity.getWindow(), sharedElementNames, acceptedNames, mappedNames, - activity.mTransitionListener); + getListener(activity, acceptedNames), acceptedNames != null); mActivity = activity; - mIsReturning = acceptedNames != null; setResultReceiver(resultReceiver); prepareEnter(); Bundle resultReceiverBundle = new Bundle(); @@ -80,6 +78,12 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { } } + private static SharedElementListener getListener(Activity activity, + ArrayList acceptedNames) { + boolean isReturning = acceptedNames != null; + return isReturning ? activity.mExitTransitionListener : activity.mEnterTransitionListener; + } + @Override protected void onReceiveResult(int resultCode, Bundle resultData) { switch (resultCode) { @@ -299,7 +303,6 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { if (sharedElementBundle != null) { Bitmap bitmap = sharedElementBundle.getParcelable(KEY_BITMAP); View snapshot = new View(context); - snapshot.setId(com.android.internal.R.id.shared_element); Resources resources = getWindow().getContext().getResources(); snapshot.setBackground(new BitmapDrawable(resources, bitmap)); snapshot.setViewName(name); @@ -420,12 +423,4 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { } } - @Override - protected Transition getViewsTransition() { - return getWindow().getEnterTransition(); - } - - protected Transition getSharedElementTransition() { - return getWindow().getSharedElementEnterTransition(); - } } diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index 43a60a3055456..1d78b3045eb05 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -53,20 +53,22 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { private boolean mIsBackgroundReady; - private boolean mIsReturning; - private boolean mIsCanceled; private Handler mHandler; public ExitTransitionCoordinator(Activity activity, ArrayList names, ArrayList accepted, ArrayList mapped, boolean isReturning) { - super(activity.getWindow(), names, accepted, mapped, activity.mTransitionListener); - mIsReturning = isReturning; + super(activity.getWindow(), names, accepted, mapped, getListener(activity, isReturning), + isReturning); mIsBackgroundReady = !mIsReturning; mActivity = activity; } + private static SharedElementListener getListener(Activity activity, boolean isReturning) { + return isReturning ? activity.mExitTransitionListener : activity.mEnterTransitionListener; + } + @Override protected void onReceiveResult(int resultCode, Bundle resultData) { switch (resultCode) { @@ -271,13 +273,4 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { } return -1; } - - @Override - protected Transition getViewsTransition() { - return getWindow().getExitTransition(); - } - - protected Transition getSharedElementTransition() { - return getWindow().getSharedElementExitTransition(); - } } diff --git a/core/java/android/app/SharedElementListener.java b/core/java/android/app/SharedElementListener.java index d4bc019f2a1df..e03e42e98a933 100644 --- a/core/java/android/app/SharedElementListener.java +++ b/core/java/android/app/SharedElementListener.java @@ -22,15 +22,27 @@ import java.util.Map; /** * Listener provided in - * {@link Activity#setSharedElementListener(SharedElementListener)} - * to monitor the Activity transitions. The events can be used to customize or override Activity + * {@link Activity#setEnterSharedElementListener(SharedElementListener)} and + * {@link Activity#setExitSharedElementListener(SharedElementListener)} + * to monitor the Activity transitions. The events can be used to customize Activity * Transition behavior. */ -public class SharedElementListener { +public abstract class SharedElementListener { + + static final SharedElementListener NULL_LISTENER = new SharedElementListener() { + }; + /** - * Called to allow the listener to customize the start state of the shared element for - * the shared element entering transition. By default, the shared element is placed in - * the position and with the size of the shared element in the calling Activity or Fragment. + * Called to allow the listener to customize the start state of the shared element when + * transferring in shared element state. + *

+ * The shared element will start at the size and position of the shared element + * in the launching Activity or Fragment. It will also transfer ImageView scaleType + * and imageMatrix if the shared elements in the calling and called Activities are + * ImageViews. Some applications may want to make additional changes, such as + * changing the clip bounds, scaling, or rotation if the shared element end state + * does not map well to the start state. + *

* * @param sharedElementNames The names of the shared elements that were accepted into * the View hierarchy. @@ -44,8 +56,17 @@ public class SharedElementListener { List sharedElements, List sharedElementSnapshots) {} /** - * Called to allow the listener to customize the end state of the shared element for - * the shared element entering transition. + * Called to allow the listener to customize the end state of the shared element when + * transferring in shared element state. + *

+ * Any customization done in + * {@link #setSharedElementStart(java.util.List, java.util.List, java.util.List)} + * may need to be modified to the final state of the shared element if it is not + * automatically corrected by layout. For example, rotation or scale will not + * be affected by layout and if changed in {@link #setSharedElementStart(java.util.List, + * java.util.List, java.util.List)}, it will also have to be set here again to correct + * the end state. + *

* * @param sharedElementNames The names of the shared elements that were accepted into * the View hierarchy. @@ -59,13 +80,18 @@ public class SharedElementListener { List sharedElements, List sharedElementSnapshots) {} /** - * If nothing is done, all shared elements that were not accepted by - * {@link #remapSharedElements(java.util.List, java.util.Map)} will be Transitioned - * out of the entering scene automatically. Any elements removed from - * rejectedSharedElements must be handled by the ActivityTransitionListener. - *

Views in rejectedSharedElements will have their position and size set to the - * position of the calling shared element, relative to the Window decor View. This - * view may be safely added to the decor View's overlay to remain in position.

+ * Called after {@link #remapSharedElements(java.util.List, java.util.Map)} when + * transferring shared elements in. Any shared elements that have no mapping will be in + * rejectedSharedElements. The elements remaining in + * rejectedSharedElements will be transitioned out of the Scene. If a + * View is removed from rejectedSharedElements, it must be handled by the + * SharedElementListener. + *

+ * Views in rejectedSharedElements will have their position and size set to the + * position of the calling shared element, relative to the Window decor View and contain + * snapshots of the View from the calling Activity or Fragment. This + * view may be safely added to the decor View's overlay to remain in position. + *

* * @param rejectedSharedElements Views containing visual information of shared elements * that are not part of the entering scene. These Views @@ -78,6 +104,7 @@ public class SharedElementListener { /** * Lets the ActivityTransitionListener adjust the mapping of shared element names to * Views. + * * @param names The names of all shared elements transferred from the calling Activity * to the started Activity. * @param sharedElements The mapping of shared element names to Views. The best guess diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml index 6ea0fae52ff7a..c966a12b7c9b4 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -83,5 +83,4 @@ - diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 44b25f2be412c..1bb0d42024c13 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2186,7 +2186,6 @@ -