Merge "Import updated SearchView assets from UX"
diff --git a/api/current.txt b/api/current.txt
index ac04dd1..c0ed81a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -543,6 +543,7 @@
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 = 16843774; // 0x10103fe
field public static final int fromXDelta = 16843206; // 0x10101c6
field public static final int fromXScale = 16843202; // 0x10101c2
field public static final int fromYDelta = 16843208; // 0x10101c8
@@ -960,6 +961,7 @@
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 = 16843776; // 0x1010400
field public static final int sharedUserId = 16842763; // 0x101000b
field public static final int sharedUserLabel = 16843361; // 0x1010261
field public static final int shouldDisableView = 16843246; // 0x10101ee
@@ -1142,6 +1144,7 @@
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 = 16843775; // 0x10103ff
field public static final int toXDelta = 16843207; // 0x10101c7
field public static final int toXScale = 16843203; // 0x10101c3
field public static final int toYDelta = 16843209; // 0x10101c9
@@ -1157,6 +1160,7 @@
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 = 16843777; // 0x1010401
field public static final int transitionOrdering = 16843744; // 0x10103e0
field public static final int translationX = 16843554; // 0x1010322
field public static final int translationY = 16843555; // 0x1010323
@@ -1514,6 +1518,7 @@
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_name = 16908334; // 0x102002e
field public static final int startSelectingText = 16908328; // 0x1020028
field public static final int stopSelectingText = 16908329; // 0x1020029
field public static final int summary = 16908304; // 0x1020010
@@ -3035,6 +3040,7 @@
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();
@@ -3130,6 +3136,7 @@
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);
@@ -3170,6 +3177,7 @@
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);
@@ -3340,6 +3348,7 @@
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 makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
method public android.os.Bundle toBundle();
method public void update(android.app.ActivityOptions);
@@ -18378,7 +18387,7 @@
public abstract class CountDownTimer {
ctor public CountDownTimer(long, long);
- method public final void cancel();
+ method public final synchronized void cancel();
method public abstract void onFinish();
method public abstract void onTick(long);
method public final synchronized android.os.CountDownTimer start();
@@ -26682,6 +26691,7 @@
method public android.transition.Transition addListener(android.transition.Transition.TransitionListener);
method public android.transition.Transition addTarget(int);
method public android.transition.Transition addTarget(android.view.View);
+ method public boolean canRemoveViews();
method public abstract void captureEndValues(android.transition.TransitionValues);
method public abstract void captureStartValues(android.transition.TransitionValues);
method public android.transition.Transition clone();
@@ -28746,6 +28756,7 @@
method public int getScrollBarStyle();
method public final int getScrollX();
method public final int getScrollY();
+ method public java.lang.String getSharedElementName();
method public int getSolidColor();
method protected int getSuggestedMinimumHeight();
method protected int getSuggestedMinimumWidth();
@@ -28999,6 +29010,7 @@
method public void setScrollY(int);
method public void setScrollbarFadingEnabled(boolean);
method public void setSelected(boolean);
+ method public void setSharedElementName(java.lang.String);
method public void setSoundEffectsEnabled(boolean);
method public void setSystemUiVisibility(int);
method public void setTag(java.lang.Object);
@@ -29385,6 +29397,7 @@
method protected boolean isChildrenDrawingOrderEnabled();
method protected boolean isChildrenDrawnWithCacheEnabled();
method public boolean isMotionEventSplittingEnabled();
+ method public boolean isTransitionGroup();
method public final void layout(int, int, int, int);
method protected void measureChild(android.view.View, int, int);
method protected void measureChildWithMargins(android.view.View, int, int, int, int);
@@ -29430,6 +29443,7 @@
method public void setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener);
method public void setPersistentDrawingCache(int);
method protected void setStaticTransformationsEnabled(boolean);
+ method public void setTransitionGroup(boolean);
method public boolean shouldDelayChildPressedState();
method public boolean showContextMenuForChild(android.view.View);
method public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
@@ -29724,7 +29738,6 @@
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 setTransitionOptions(android.os.Bundle);
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 698f06a..a8716bf 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -18,7 +18,6 @@
import android.annotation.NonNull;
import android.transition.Scene;
-import android.transition.Transition;
import android.transition.TransitionManager;
import android.util.ArrayMap;
import android.util.SuperNotCalledException;
@@ -771,6 +770,7 @@
private Thread mUiThread;
final Handler mHandler = new Handler();
+ private ActivityOptions mTransitionActivityOptions;
/** Return the intent that started this activity. */
public Intent getIntent() {
@@ -3443,38 +3443,16 @@
*
* @throws android.content.ActivityNotFoundException
*
- * @see #startActivity
+ * @see #startActivity
*/
public void startActivityForResult(Intent intent, int requestCode) {
- final TransitionManager tm = getWindow().getTransitionManager();
- final Scene currScene = getWindow().getContentScene();
- final String[] targetSceneNames = currScene != null && tm != null ?
- tm.getTargetSceneNames(currScene) : null;
-
- if (targetSceneNames == null || targetSceneNames.length == 0) {
- startActivityForResult(intent, requestCode, null);
- } else {
- // TODO Capture the scene transition args and send along
- final ActivityOptions opts = ActivityOptions.makeSceneTransitionAnimation(
- targetSceneNames, null,
- new ActivityOptions.OnSceneTransitionStartedListener() {
- @Override public void onSceneTransitionStarted(String destSceneName) {
- final Transition t = tm.getNamedTransition(currScene, destSceneName);
- // TODO Fill this in to notify the outgoing activity that it should
- // treat this as a sync point for the transition - the target
- // transition has started.
- Log.d(TAG, "Scene transition to scene " + destSceneName +
- " transition " + t);
- }
- }, mHandler);
- startActivityForResult(intent, requestCode, opts.toBundle());
- }
+ startActivityForResult(intent, requestCode, null);
}
/**
* Launch an activity for which you would like a result when it finished.
* When this activity exits, your
- * onActivityResult() method will be called with the given requestCode.
+ * onActivityResult() method will be called with the given requestCode.
* Using a negative requestCode is the same as calling
* {@link #startActivity} (the activity is not launched as a sub-activity).
*
@@ -3487,9 +3465,9 @@
*
* <p>As a special case, if you call startActivityForResult() with a requestCode
* >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
- * activity, then your window will not be displayed until a result is
- * returned back from the started activity. This is to avoid visible
- * flickering when redirecting to another activity.
+ * activity, then your window will not be displayed until a result is
+ * returned back from the started activity. This is to avoid visible
+ * flickering when redirecting to another activity.
*
* <p>This method throws {@link android.content.ActivityNotFoundException}
* if there was no Activity found to run the given Intent.
@@ -3503,9 +3481,17 @@
*
* @throws android.content.ActivityNotFoundException
*
- * @see #startActivity
+ * @see #startActivity
*/
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
+ TransitionManager tm = getContentTransitionManager();
+ if (tm != null && options != null) {
+ ActivityOptions activityOptions = new ActivityOptions(options);
+ if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
+ getWindow().startExitTransition(activityOptions);
+ options = activityOptions.toBundle();
+ }
+ }
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
@@ -5313,7 +5299,7 @@
mWindow.setUiOptions(info.uiOptions);
}
mUiThread = Thread.currentThread();
-
+
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
@@ -5335,8 +5321,40 @@
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
- mWindow.setTransitionOptions(options);
mCurrentConfig = config;
+ mTransitionActivityOptions = null;
+ Window.SceneTransitionListener sceneTransitionListener = null;
+ if (options != null) {
+ ActivityOptions activityOptions = new ActivityOptions(options);
+ if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
+ mTransitionActivityOptions = activityOptions;
+ sceneTransitionListener = new Window.SceneTransitionListener() {
+ @Override
+ public void enterSharedElement(Bundle transitionArgs) {
+ startSharedElementTransition(transitionArgs);
+ mTransitionActivityOptions = null;
+ }
+
+ @Override
+ public void nullPendingTransition() {
+ overridePendingTransition(0, 0);
+ }
+
+ @Override
+ public void convertFromTranslucent() {
+ Activity.this.convertFromTranslucent();
+ }
+
+ @Override
+ public void convertToTranslucent() {
+ Activity.this.convertToTranslucent(null);
+ }
+ };
+
+ }
+ }
+
+ mWindow.setTransitionOptions(mTransitionActivityOptions, sceneTransitionListener);
}
/** @hide */
@@ -5350,7 +5368,7 @@
com.android.internal.R.styleable.Window_windowNoDisplay, false);
mFragments.dispatchActivityCreated();
}
-
+
final void performStart() {
mFragments.noteStateNotSaved();
mCalled = false;
@@ -5507,7 +5525,7 @@
}
}
}
-
+
mStopped = true;
}
mResumed = false;
@@ -5522,7 +5540,57 @@
mLoaderManager.doDestroy();
}
}
-
+
+ /**
+ * 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>
+ *
+ * @return The Bundle passed into Bundle parameter of
+ * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)}
+ * in the calling Activity.
+ */
+ public Bundle getTransitionArgs() {
+ if (mTransitionActivityOptions == null) {
+ return null;
+ }
+ return mTransitionActivityOptions.getSceneTransitionArgs();
+ }
+
+ /**
+ * 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.
+ */
+ 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);
+ }
+
/**
* @hide
*/
@@ -5530,7 +5598,7 @@
return mResumed;
}
- void dispatchActivityResult(String who, int requestCode,
+ void dispatchActivityResult(String who, int requestCode,
int resultCode, Intent data) {
if (false) Log.v(
TAG, "Dispatching result: who=" + who + ", reqCode=" + requestCode
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 582ce3c..3f97c40 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -16,16 +16,21 @@
package android.app;
+import android.animation.Animator;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.RemoteException;
-import android.text.TextUtils;
+import android.transition.Transition;
+import android.util.ArrayMap;
import android.util.Log;
import android.view.View;
+import java.util.ArrayList;
+import java.util.Map;
+
/**
* Helper class for building an options Bundle that can be used with
* {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
@@ -95,34 +100,30 @@
public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
/**
- * A string array of names for the destination scene. This defines an API in the same
- * way that intent action or extra names do and should follow a similar convention:
- * "com.example.scene.FOO"
- *
- * @hide
- */
- public static final String KEY_DEST_SCENE_NAMES = "android:destSceneNames";
-
- /**
- * A string indicating the destination scene name that was chosen by the target.
- * Used by {@link OnSceneTransitionStartedListener}.
- * @hide
- */
- public static final String KEY_DEST_SCENE_NAME_CHOSEN = "android:destSceneNameChosen";
-
- /**
- * Callback for when scene transition is started.
- * @hide
- */
- public static final String KEY_SCENE_TRANSITION_START_LISTENER =
- "android:sceneTransitionStartListener";
-
- /**
* 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.
+ */
+ private static final String KEY_TRANSITION_COMPLETE_LISTENER
+ = "android:transitionCompleteListener";
+
+ /**
+ * For Activity transitions, the called Activity's listener to receive calls
+ * when transitions complete.
+ */
+ private static final String KEY_TRANSITION_TARGET_LISTENER = "android:transitionTargetListener";
+
+ /**
+ * The shared element's texture ID (TODO: not used yet).
+ */
+ private static final String KEY_SHARED_ELEMENT_TEXTURE_ID = "android:sharedElementTextureId";
+
/** @hide */
public static final int ANIM_NONE = 0;
/** @hide */
@@ -145,10 +146,9 @@
private int mStartY;
private int mStartWidth;
private int mStartHeight;
- private String[] mDestSceneNames;
private Bundle mTransitionArgs;
private IRemoteCallback mAnimationStartedListener;
- private IRemoteCallback mSceneTransitionStartedListener;
+ private IRemoteCallback mTransitionCompleteListener;
/**
* Create an ActivityOptions specifying a custom animation to run when
@@ -215,24 +215,6 @@
}
}
- private void setOnSceneTransitionStartedListener(Handler handler,
- OnSceneTransitionStartedListener listener) {
- if (listener != null) {
- final Handler h = handler;
- final OnSceneTransitionStartedListener l = listener;
- mSceneTransitionStartedListener = new IRemoteCallback.Stub() {
- @Override public void sendResult(final Bundle data) throws RemoteException {
- h.post(new Runnable() {
- public void run() {
- l.onSceneTransitionStarted(data != null ?
- data.getString(KEY_DEST_SCENE_NAME_CHOSEN) : null);
- }
- });
- }
- };
- }
- }
-
/**
* Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
* to find out when the given animation has started running.
@@ -242,13 +224,10 @@
void onAnimationStarted();
}
- /**
- * Callback for use with {@link ActivityOptions#makeSceneTransitionAnimation}
- * to find out when a transition is about to begin.
- * @hide
- */
- public interface OnSceneTransitionStartedListener {
- void onSceneTransitionStarted(String destSceneName);
+ /** @hide */
+ public interface ActivityTransitionTarget {
+ void sharedElementTransitionComplete();
+ void exitTransitionComplete();
}
/**
@@ -369,18 +348,35 @@
}
/**
- * Create an ActivityOptions specifying an animation where an activity window is asked
- * to perform animations within the window content.
+ * 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.
*
- * @hide
+ * 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>
+ *
+ * <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 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)
*/
- public static ActivityOptions makeSceneTransitionAnimation(String[] destSceneNames,
- Bundle args, OnSceneTransitionStartedListener listener, Handler handler) {
+ public static ActivityOptions makeSceneTransitionAnimation(Bundle args) {
ActivityOptions opts = new ActivityOptions();
opts.mAnimationType = ANIM_SCENE_TRANSITION;
- opts.mDestSceneNames = destSceneNames;
opts.mTransitionArgs = args;
- opts.setOnSceneTransitionStartedListener(handler, listener);
return opts;
}
@@ -416,10 +412,9 @@
break;
case ANIM_SCENE_TRANSITION:
- mDestSceneNames = opts.getStringArray(KEY_DEST_SCENE_NAMES);
mTransitionArgs = opts.getBundle(KEY_SCENE_TRANSITION_ARGS);
- mSceneTransitionStartedListener = IRemoteCallback.Stub.asInterface(
- opts.getBinder(KEY_SCENE_TRANSITION_START_LISTENER));
+ mTransitionCompleteListener = IRemoteCallback.Stub.asInterface(
+ opts.getBinder(KEY_TRANSITION_COMPLETE_LISTENER));
break;
}
}
@@ -470,11 +465,6 @@
}
/** @hide */
- public String[] getDestSceneNames() {
- return mDestSceneNames;
- }
-
- /** @hide */
public Bundle getSceneTransitionArgs() {
return mTransitionArgs;
}
@@ -485,19 +475,33 @@
}
/** @hide */
- public void dispatchSceneTransitionStarted(String destScene) {
- if (mSceneTransitionStartedListener != null) {
- Bundle data = null;
- if (!TextUtils.isEmpty(destScene)) {
- data = new Bundle();
- data.putString(KEY_DEST_SCENE_NAME_CHOSEN, destScene);
- }
+ public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target) {
+ boolean listenerSent = false;
+ if (mTransitionCompleteListener != null) {
+ IRemoteCallback callback = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data) throws RemoteException {
+ if (data == null) {
+ target.exitTransitionComplete();
+ } else {
+ // TODO: Use texture id
+ target.sharedElementTransitionComplete();
+ }
+ }
+ };
+ Bundle bundle = new Bundle();
+ bundle.putBinder(KEY_TRANSITION_TARGET_LISTENER, callback.asBinder());
try {
- mSceneTransitionStartedListener.sendResult(data);
+ mTransitionCompleteListener.sendResult(bundle);
+ listenerSent = true;
} catch (RemoteException e) {
- Log.e(TAG, "Caught exception dispatching scene transition start", e);
+ Log.w(TAG, "Couldn't retrieve transition notifications", e);
}
}
+ if (!listenerSent) {
+ target.sharedElementTransitionComplete();
+ target.exitTransitionComplete();
+ }
}
/** @hide */
@@ -508,12 +512,6 @@
} catch (RemoteException e) {
}
}
- if (mSceneTransitionStartedListener != null) {
- try {
- mSceneTransitionStartedListener.sendResult(null);
- } catch (RemoteException e) {
- }
- }
}
/** @hide */
@@ -545,9 +543,8 @@
}
}
mAnimationStartedListener = otherOptions.mAnimationStartedListener;
- mSceneTransitionStartedListener = null;
+ mTransitionCompleteListener = null;
mTransitionArgs = null;
- mDestSceneNames = null;
break;
case ANIM_SCALE_UP:
mAnimationType = otherOptions.mAnimationType;
@@ -562,9 +559,8 @@
}
}
mAnimationStartedListener = null;
- mSceneTransitionStartedListener = null;
+ mTransitionCompleteListener = null;
mTransitionArgs = null;
- mDestSceneNames = null;
break;
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
@@ -579,20 +575,12 @@
}
}
mAnimationStartedListener = otherOptions.mAnimationStartedListener;
- mSceneTransitionStartedListener = null;
+ mTransitionCompleteListener = null;
mTransitionArgs = null;
- mDestSceneNames = null;
break;
case ANIM_SCENE_TRANSITION:
mAnimationType = otherOptions.mAnimationType;
- if (mSceneTransitionStartedListener != null) {
- try {
- mSceneTransitionStartedListener.sendResult(null);
- } catch (RemoteException e) {
- }
- }
- mSceneTransitionStartedListener = otherOptions.mSceneTransitionStartedListener;
- mDestSceneNames = otherOptions.mDestSceneNames;
+ mTransitionCompleteListener = otherOptions.mTransitionCompleteListener;
mTransitionArgs = otherOptions.mTransitionArgs;
mThumbnail = null;
mAnimationStartedListener = null;
@@ -639,10 +627,11 @@
break;
case ANIM_SCENE_TRANSITION:
b.putInt(KEY_ANIM_TYPE, mAnimationType);
- b.putStringArray(KEY_DEST_SCENE_NAMES, mDestSceneNames);
b.putBundle(KEY_SCENE_TRANSITION_ARGS, mTransitionArgs);
- b.putBinder(KEY_SCENE_TRANSITION_START_LISTENER, mSceneTransitionStartedListener
- != null ? mSceneTransitionStartedListener.asBinder() : null);
+ if (mTransitionCompleteListener != null) {
+ b.putBinder(KEY_TRANSITION_COMPLETE_LISTENER,
+ mTransitionCompleteListener.asBinder());
+ }
break;
}
return b;
@@ -661,4 +650,123 @@
return null;
}
+
+ /** @hide */
+ public interface SharedElementSource {
+ int getTextureId();
+ }
+
+ /**
+ * 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);
+ }
+
+ private static class ExitTransitionListener extends IRemoteCallback.Stub
+ implements Transition.TransitionListener, Animator.AnimatorListener {
+ private ArrayList<Animator> mSharedElementAnimators = new ArrayList<Animator>();
+ private boolean mSharedElementNotified;
+ private Transition mExitTransition;
+ private IRemoteCallback mTransitionCompleteCallback;
+ private boolean mExitComplete;
+ private SharedElementSource mSharedElementSource;
+
+ public ExitTransitionListener(Transition transition, SharedElementSource sharedElementSource) {
+ mSharedElementSource = sharedElementSource;
+ mExitTransition = transition;
+ mExitTransition.addListener(this);
+ }
+
+ @Override
+ public void sendResult(Bundle data) throws RemoteException {
+ if (data != null) {
+ mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface(
+ data.getBinder(KEY_TRANSITION_TARGET_LISTENER));
+ notifySharedElement();
+ notifyExit();
+ }
+ }
+
+ @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);
+ }
+
+ @Override
+ public void onTransitionCancel(Transition transition) {
+ mExitComplete = true;
+ notifyExit();
+ mExitTransition.removeListener(this);
+ }
+
+ @Override
+ public void onTransitionPause(Transition transition) {
+ }
+
+ @Override
+ 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()
+ && mTransitionCompleteCallback != null) {
+ mSharedElementNotified = true;
+ try {
+ Bundle bundle = new Bundle();
+ bundle.putInt(KEY_SHARED_ELEMENT_TEXTURE_ID, mSharedElementSource.getTextureId());
+ mTransitionCompleteCallback.sendResult(bundle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Couldn't notify that the transition ended", e);
+ }
+ }
+ }
+
+ private void notifyExit() {
+ if (mExitComplete && mTransitionCompleteCallback != null) {
+ try {
+ mTransitionCompleteCallback.sendResult(null);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Couldn't notify that the transition ended", e);
+ }
+ }
+ }
+ }
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index bb8b184..913b273 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -398,16 +398,44 @@
new Key<Byte>("android.quirks.usePartialResult", byte.class);
/**
- * <p>How many output streams can be allocated at
- * the same time for each type of stream</p>
- * <p>Video snapshot with preview callbacks requires 3
- * processed streams (preview, record, app callbacks) and
- * one JPEG stream (snapshot)</p>
+ * <p>The maximum numbers of different types of output streams
+ * that can be configured and used simultaneously by a camera device.</p>
+ * <p>This is a 3 element tuple that contains the max number of output simultaneous
+ * streams for raw sensor, processed (and uncompressed), and JPEG formats respectively.
+ * For example, if max raw sensor format output stream number is 1, max YUV streams
+ * number is 3, and max JPEG stream number is 2, then this tuple should be <code>(1, 3, 2)</code>.</p>
+ * <p>This lists the upper bound of the number of output streams supported by
+ * the camera device. Using more streams simultaneously may require more hardware and
+ * CPU resources that will consume more power. The image format for a output stream can
+ * be any supported format provided by {@link CameraCharacteristics#SCALER_AVAILABLE_FORMATS android.scaler.availableFormats}. The formats
+ * defined in {@link CameraCharacteristics#SCALER_AVAILABLE_FORMATS android.scaler.availableFormats} can be catergorized into the 3 stream types
+ * as below:</p>
+ * <ul>
+ * <li>JPEG-compressed format: BLOB.</li>
+ * <li>Raw formats: RAW_SENSOR and RAW_OPAQUE.</li>
+ * <li>processed, uncompressed formats: YCbCr_420_888, YCrCb_420_SP, YV12.</li>
+ * </ul>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_FORMATS
*/
public static final Key<int[]> REQUEST_MAX_NUM_OUTPUT_STREAMS =
new Key<int[]>("android.request.maxNumOutputStreams", int[].class);
/**
+ * <p>The maximum numbers of any type of input streams
+ * that can be configured and used simultaneously by a camera device.</p>
+ * <p>When set to 0, it means no input stream is supported.</p>
+ * <p>The image format for a input stream can be any supported format provided
+ * by android.scaler.availableInputFormats. When using an input stream, there must be
+ * at least one output stream configured to to receive the reprocessed images.</p>
+ * <p>For example, for Zero Shutter Lag (ZSL) still capture use case, the input
+ * stream image format will be RAW_OPAQUE, the associated output stream image format
+ * should be JPEG.</p>
+ */
+ public static final Key<Integer> REQUEST_MAX_NUM_INPUT_STREAMS =
+ new Key<Integer>("android.request.maxNumInputStreams", int.class);
+
+ /**
* <p>Specifies the number of maximum pipeline stages a frame
* has to go through from when it's exposed to when it's available
* to the framework.</p>
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index da9ba5a..fd3f9b3 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -552,7 +552,8 @@
return false;
}
- private static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
+ /** @hide */
+ public static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
ArrayMap<Animator, AnimationInfo> runningAnimators = sRunningAnimators.get();
if (runningAnimators == null) {
runningAnimators = new ArrayMap<Animator, AnimationInfo>();
@@ -1077,6 +1078,9 @@
if (view == null) {
return;
}
+ if (!isValidTarget(view, view.getId())) {
+ return;
+ }
boolean isListViewItem = false;
if (view.getParent() instanceof ListView) {
isListViewItem = true;
@@ -1467,6 +1471,10 @@
mCanRemoveViews = canRemoveViews;
}
+ public boolean canRemoveViews() {
+ return mCanRemoveViews;
+ }
+
@Override
public String toString() {
return toString("");
@@ -1629,9 +1637,10 @@
* animation should be canceled or a new animation noop'd. The structure holds
* information about the state that an animation is going to, to be compared to
* end state of a new animation.
+ * @hide
*/
- private static class AnimationInfo {
- View view;
+ public static class AnimationInfo {
+ public View view;
String name;
TransitionValues values;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4b6f2b0..518908f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -665,6 +665,7 @@
* @attr ref android.R.styleable#View_scrollbarTrackVertical
* @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
* @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
+ * @attr ref android.R.styleable#View_sharedElementName
* @attr ref android.R.styleable#View_soundEffectsEnabled
* @attr ref android.R.styleable#View_tag
* @attr ref android.R.styleable#View_textAlignment
@@ -4038,6 +4039,9 @@
case R.styleable.View_accessibilityLiveRegion:
setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
break;
+ case R.styleable.View_sharedElementName:
+ setSharedElementName(a.getString(attr));
+ break;
}
}
@@ -18872,6 +18876,35 @@
}
/**
+ * Specifies that the shared name of the View to be shared with another Activity.
+ * When transitioning between Activities, the name links a UI element in the starting
+ * Activity to UI element in the called Activity. Names should be unique in the
+ * View hierarchy.
+ *
+ * @param sharedElementName The cross-Activity View identifier. The called Activity will use
+ * the name to match the location with a View in its layout.
+ * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
+ */
+ public void setSharedElementName(String sharedElementName) {
+ setTagInternal(com.android.internal.R.id.shared_element_name, sharedElementName);
+ }
+
+ /**
+ * Returns the shared name of the View to be shared with another Activity.
+ * When transitioning between Activities, the name links a UI element in the starting
+ * Activity to UI element in the called Activity. Names should be unique in the
+ * View hierarchy.
+ *
+ * <p>This returns null if the View is not a shared element or the name if it is.</p>
+ *
+ * @return The name used for this View for cross-Activity transitions or null if
+ * this View has not been identified as shared.
+ */
+ public String getSharedElementName() {
+ return (String) getTag(com.android.internal.R.id.shared_element_name);
+ }
+
+ /**
* Interface definition for a callback to be invoked when a hardware key event is
* dispatched to this view. The callback will be invoked before the key event is
* given to the view. This is only useful for hardware keyboards; a software input
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index b91091f..73b108f 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -360,6 +360,10 @@
*/
static final int FLAG_ISOLATED_Z_VOLUME = 0x1000000;
+ static final int FLAG_IS_TRANSITION_GROUP = 0x2000000;
+
+ static final int FLAG_IS_TRANSITION_GROUP_SET = 0x4000000;
+
/**
* Indicates which types of drawing caches are to be kept in memory.
* This field should be made private, so it is hidden from the SDK.
@@ -556,6 +560,9 @@
case R.styleable.ViewGroup_layoutMode:
setLayoutMode(a.getInt(attr, LAYOUT_MODE_UNDEFINED));
break;
+ case R.styleable.ViewGroup_transitionGroup:
+ setTransitionGroup(a.getBoolean(attr, false));
+ break;
}
}
@@ -2288,6 +2295,41 @@
}
/**
+ * Returns true if this ViewGroup should be considered as a single entity for removal
+ * when executing an Activity transition. If this is false, child elements will move
+ * 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)
+ */
+ public boolean isTransitionGroup() {
+ if ((mGroupFlags & FLAG_IS_TRANSITION_GROUP_SET) != 0) {
+ return ((mGroupFlags & FLAG_IS_TRANSITION_GROUP) != 0);
+ } else {
+ return getBackground() != null;
+ }
+ }
+
+ /**
+ * Changes whether or not this ViewGroup should be treated as a single entity during
+ * ActivityTransitions.
+ * @param isTransitionGroup Whether or not the ViewGroup should be treated as a unit
+ * in Activity transitions. If false, the ViewGroup won't transition,
+ * only its children. If true, the entire ViewGroup will transition
+ * together.
+ * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
+ */
+ public void setTransitionGroup(boolean isTransitionGroup) {
+ mGroupFlags |= FLAG_IS_TRANSITION_GROUP_SET;
+ if (isTransitionGroup) {
+ mGroupFlags |= FLAG_IS_TRANSITION_GROUP;
+ } else {
+ mGroupFlags &= ~FLAG_IS_TRANSITION_GROUP;
+ }
+ }
+
+ /**
* {@inheritDoc}
*/
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 1064a08..11740ab 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityOptions;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
@@ -1374,8 +1375,41 @@
/**
* Set options that can affect the transition behavior within this window.
* @param options Options to set or null for none
+ * @hide
*/
- public void setTransitionOptions(Bundle options) {
- throw new UnsupportedOperationException();
+ public void setTransitionOptions(ActivityOptions options, SceneTransitionListener listener) {
+ }
+
+ /**
+ * A callback for Activity transitions to be told when the shared element is ready to be shown
+ * and start the transition to its target location.
+ * @hide
+ */
+ public interface SceneTransitionListener {
+ void enterSharedElement(Bundle transitionArgs);
+ void nullPendingTransition();
+ void convertFromTranslucent();
+ void convertToTranslucent();
+ }
+
+ /**
+ * 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.
+ *
+ * @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
+ */
+ public void setEarlyBackgroundTransition(boolean fadeEarly) {
+ }
+
+ /**
+ * Start the exit transition.
+ * @hide
+ */
+ public void startExitTransition(ActivityOptions activityOptions) {
}
}
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 3116955..5d49204 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -141,7 +141,8 @@
*needsDetach = false;
JNIEnv* env = AndroidRuntime::getJNIEnv();
if (env == NULL) {
- JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
+ JavaVMAttachArgs args = {
+ JNI_VERSION_1_4, "JNISurfaceTextureContext", NULL };
JavaVM* vm = AndroidRuntime::getJavaVM();
int result = vm->AttachCurrentThread(&env, (void*) &args);
if (result != JNI_OK) {
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f77d66b..9526e13 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2250,6 +2250,11 @@
view with a theme override will inherit the themed context. -->
<attr name="theme" />
+ <!-- Specifies that the shared name of the View to be shared with another Activity.
+ When transitioning between Activities, the name links a UI element in the starting
+ Activity to UI element in the called Activity. Names should be unique in the
+ View hierarchy. -->
+ <attr name="sharedElementName" format="string" />
</declare-styleable>
<!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -2336,6 +2341,14 @@
<!-- Use the children's optical bounds when laying out this container. -->
<enum name="opticalBounds" value="1" />
</attr>
+
+ <!-- Sets whether or not this ViewGroup should be treated as a single entity
+ when doing an Activity transition. Typically, the elements inside a
+ ViewGroup are each transitioned from the scene individually. The default
+ for a ViewGroup is false unless it has a background.
+ See {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)}
+ for more information. -->
+ <attr name="transitionGroup" format="boolean" />
</declare-styleable>
<!-- A {@link android.view.ViewStub} lets you lazily include other XML layouts
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 5c0baaa..56bb15f 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -82,4 +82,5 @@
<item type="id" name="action_bar_spinner" />
<item type="id" name="current_scene" />
<item type="id" name="scene_layoutid_cache" />
+ <item type="id" name="shared_element_name" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e99b5ba..722f965 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2104,6 +2104,12 @@
<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="id" name="shared_element_name" />
<public type="style" name="Widget.Holo.FragmentBreadCrumbs" />
<public type="style" name="Widget.Holo.Light.FragmentBreadCrumbs" />
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index c62510b..297a2dc 100644
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -56,7 +56,9 @@
RenderScript kernel language used in this script. Currently, 1 is the only valid value.</li>
<li>A pragma declaration (<code>#pragma rs java_package_name(com.example.app)</code>) that
-declares the package name of the Java classes reflected from this script.</li>
+declares the package name of the Java classes reflected from this script.
+Note that your .rs file must be part of your application package, and not in a
+library project.</li>
<li>Some number of invokable functions. An invokable function is a single-threaded RenderScript
function that you can call from your Java code with arbitrary arguments. These are often useful for
@@ -308,4 +310,4 @@
<li><strong>Tear down the RenderScript context.</strong> The RenderScript context can be destroyed
with {@link android.renderscript.RenderScript#destroy} or by allowing the RenderScript context
object to be garbage collected. This will cause any further use of any object belonging to that
-context to throw an exception.</li> </ol>
\ No newline at end of file
+context to throw an exception.</li> </ol>
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index a0ea53c..c73d90a 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -22,6 +22,8 @@
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowManager.LayoutParams.*;
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
import android.app.ActivityOptions;
import android.transition.Scene;
import android.transition.Transition;
@@ -88,6 +90,7 @@
import android.view.ViewParent;
import android.view.ViewRootImpl;
import android.view.ViewStub;
+import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
@@ -114,6 +117,8 @@
private final static String TAG = "PhoneWindow";
private final static boolean SWEEP_OPEN_MENU = false;
+ private static final long MAX_TRANSITION_START_WAIT = 500;
+ private static final long MAX_TRANSITION_FINISH_WAIT = 1000;
/**
* Simple callback used by the context menu and its submenus. The options
@@ -136,22 +141,21 @@
private ViewGroup mContentParent;
SurfaceHolder.Callback2 mTakeSurfaceCallback;
-
+
InputQueue.Callback mTakeInputQueueCallback;
-
+
private boolean mIsFloating;
private LayoutInflater mLayoutInflater;
private TextView mTitleView;
-
+
private ActionBarView mActionBar;
private ActionMenuPresenterCallback mActionMenuPresenterCallback;
private PanelMenuPresenterCallback mPanelMenuPresenterCallback;
private TransitionManager mTransitionManager;
private Scene mContentScene;
- private Bundle mTransitionOptions;
// The icon resource has been explicitly set elsewhere
// and should not be overwritten with a default.
@@ -233,6 +237,10 @@
}
};
+ private ActivityOptions mActivityOptions;
+ private SceneTransitionListener mSceneTransitionListener;
+ private boolean mFadeEarly = true;
+
static class WindowManagerHolder {
static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
@@ -303,11 +311,6 @@
}
@Override
- public void setTransitionOptions(Bundle options) {
- mTransitionOptions = options;
- }
-
- @Override
public void setContentView(int layoutResID) {
// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
// decor, when theme attributes and the like are crystalized. Do not check the feature
@@ -378,26 +381,11 @@
}
private void transitionTo(Scene scene) {
- Transition selected = null;
- if (mTransitionOptions != null) {
- final ActivityOptions opts = new ActivityOptions(mTransitionOptions);
- mTransitionOptions = null;
-
- String selectedName = null;
- for (String sceneName : opts.getDestSceneNames()) {
- final Transition t = mTransitionManager.getNamedTransition(sceneName, scene);
- if (t != null) {
- // TODO handle args/state; inject into t/clone with params
- selected = t;
- selectedName = sceneName;
- break;
- }
+ if (mContentScene == null) {
+ scene.enter();
+ if (mActivityOptions != null) {
+ new EnterScene().start();
}
- opts.dispatchSceneTransitionStarted(selectedName);
- }
-
- if (selected != null) {
- TransitionManager.go(scene, selected);
} else {
mTransitionManager.transitionTo(scene);
}
@@ -413,11 +401,11 @@
public void takeSurface(SurfaceHolder.Callback2 callback) {
mTakeSurfaceCallback = callback;
}
-
+
public void takeInputQueue(InputQueue.Callback callback) {
mTakeInputQueueCallback = callback;
}
-
+
@Override
public boolean isFloating() {
return mIsFloating;
@@ -3553,6 +3541,12 @@
return mVolumeControlStreamType;
}
+ private boolean isTranslucent() {
+ TypedArray a = getWindowStyle();
+ return a.getBoolean(a.getResourceId(
+ com.android.internal.R.styleable.Window_windowIsTranslucent, 0), false);
+ }
+
private static final class DrawableFeatureState {
DrawableFeatureState(int _featureId) {
featureId = _featureId;
@@ -3986,4 +3980,218 @@
void sendCloseSystemWindows(String reason) {
PhoneWindowManager.sendCloseSystemWindows(getContext(), reason);
}
+
+ @Override
+ public void setTransitionOptions(ActivityOptions options, SceneTransitionListener listener) {
+ mSceneTransitionListener = listener;
+ mActivityOptions = options;
+ }
+
+ @Override
+ public void setEarlyBackgroundTransition(boolean fadeEarly) {
+ mFadeEarly = fadeEarly;
+ }
+
+ @Override
+ public void startExitTransition(ActivityOptions activityOptions) {
+ Transition transition = mTransitionManager.getNamedTransition(getContentScene(), "null");
+ if (transition == null) {
+ transition = TransitionManager.getDefaultTransition().clone();
+ }
+ activityOptions.setExitTransition(transition, new ActivityOptions.SharedElementSource() {
+ @Override
+ public int getTextureId() {
+ // TODO: move shared elements to a layer and return the texture id
+ recurseHideExitingSharedElements(mContentParent);
+ return 0;
+ }
+ });
+ 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;
+ }
+ if (child instanceof ViewGroup && !((ViewGroup)child).isTransitionGroup()) {
+ recurseExitNonSharedElements((ViewGroup) child);
+ } else {
+ child.setVisibility(View.INVISIBLE);
+ }
+ }
+ }
+
+ 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;
+ }
+ if (child.getSharedElementName() != null) {
+ sharedElements.add(child);
+ child.setVisibility(View.INVISIBLE);
+ } else if (child instanceof ViewGroup && !((ViewGroup)child).isTransitionGroup()) {
+ recurseHideViews((ViewGroup) child, nonSharedElements, sharedElements);
+ } else {
+ nonSharedElements.add(child);
+ child.setVisibility(View.INVISIBLE);
+ }
+ }
+ }
+
+ 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);
+ }
+ }
+ }
+
+ /**
+ * 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
+ * the entering transition is started, the calling Activity is notified that
+ * this Activity is ready to receive the shared element. When the calling Activity notifies
+ * that the shared element is ready, this Activity is notified through the
+ * SceneTransitionListener.
+ *
+ * This class also takes into account fading the background -- either waiting until the
+ * shared element is ready or the calling Activity's exit transition is complete.
+ */
+ private class EnterScene implements ViewTreeObserver.OnPreDrawListener, Runnable,
+ ActivityOptions.ActivityTransitionTarget, Animator.AnimatorListener {
+ private boolean mSharedElementReadyReceived;
+ private boolean mAllDone;
+ private Handler mHandler = new Handler();
+ private boolean mEnterTransitionStarted;
+ private ArrayList<View> mSharedElements = new ArrayList<View>();
+
+ public EnterScene() {
+ mSceneTransitionListener.nullPendingTransition();
+ Drawable background = getDecorView().getBackground();
+ if (background != null) {
+ setBackgroundDrawable(null);
+ background.setAlpha(0);
+ setBackgroundDrawable(background);
+ }
+ mSceneTransitionListener.convertToTranslucent();
+ }
+
+ @Override
+ public boolean onPreDraw() {
+ ViewTreeObserver observer = mContentParent.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();
+ }
+ TransitionManager.beginDelayedTransition(mContentParent, transition);
+ for (View hidden : enteringViews) {
+ hidden.setVisibility(View.VISIBLE);
+ }
+ observer.addOnPreDrawListener(this);
+ } else {
+ mHandler.postDelayed(this, MAX_TRANSITION_START_WAIT);
+ mActivityOptions.dispatchSceneTransitionStarted(this);
+ }
+ return true;
+ }
+
+ public void start() {
+ ViewTreeObserver observer = mContentParent.getViewTreeObserver();
+ observer.addOnPreDrawListener(this);
+ }
+
+ @Override
+ public void run() {
+ exitTransitionComplete();
+ }
+
+ @Override
+ public void sharedElementTransitionComplete() {
+ 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 (mFadeEarly) {
+ fadeInBackground();
+ }
+ }
+ }
+
+ private void fadeInBackground() {
+ Drawable background = getDecorView().getBackground();
+ if (background == null) {
+ mSceneTransitionListener.convertFromTranslucent();
+ } else {
+ ObjectAnimator animator = ObjectAnimator.ofInt(background, "alpha", 255);
+ animator.addListener(this);
+ animator.start();
+ }
+ }
+
+ @Override
+ public void exitTransitionComplete() {
+ if (mAllDone) {
+ return;
+ }
+ mAllDone = true;
+ sharedElementTransitionComplete();
+ mHandler.removeCallbacks(this);
+ if (!mFadeEarly) {
+ fadeInBackground();
+ }
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mSceneTransitionListener.convertFromTranslucent();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+ }
}