blob: 3f97c40149fe38113042b0895026a0c5ebc8c4ad [file] [log] [blame]
Dianne Hackborn6de01a92012-03-19 19:07:40 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
George Mount0a778ed2013-12-13 13:35:36 -080019import android.animation.Animator;
Dianne Hackborn6de01a92012-03-19 19:07:40 -070020import android.content.Context;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -070021import android.graphics.Bitmap;
Dianne Hackborn6de01a92012-03-19 19:07:40 -070022import android.os.Bundle;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -070023import android.os.Handler;
24import android.os.IRemoteCallback;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -070025import android.os.RemoteException;
George Mount0a778ed2013-12-13 13:35:36 -080026import android.transition.Transition;
27import android.util.ArrayMap;
Adam Powellcfbe9be2013-11-06 14:58:58 -080028import android.util.Log;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -070029import android.view.View;
Dianne Hackborn6de01a92012-03-19 19:07:40 -070030
George Mount0a778ed2013-12-13 13:35:36 -080031import java.util.ArrayList;
32import java.util.Map;
33
Dianne Hackborn6de01a92012-03-19 19:07:40 -070034/**
35 * Helper class for building an options Bundle that can be used with
36 * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
37 * Context.startActivity(Intent, Bundle)} and related methods.
38 */
39public class ActivityOptions {
Adam Powellcfbe9be2013-11-06 14:58:58 -080040 private static final String TAG = "ActivityOptions";
41
Dianne Hackborn6de01a92012-03-19 19:07:40 -070042 /**
43 * The package name that created the options.
44 * @hide
45 */
46 public static final String KEY_PACKAGE_NAME = "android:packageName";
47
48 /**
Dianne Hackborn8078d8c2012-03-20 11:11:26 -070049 * Type of animation that arguments specify.
50 * @hide
51 */
52 public static final String KEY_ANIM_TYPE = "android:animType";
53
54 /**
Dianne Hackborn6de01a92012-03-19 19:07:40 -070055 * Custom enter animation resource ID.
56 * @hide
57 */
58 public static final String KEY_ANIM_ENTER_RES_ID = "android:animEnterRes";
59
60 /**
61 * Custom exit animation resource ID.
62 * @hide
63 */
64 public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes";
65
Dianne Hackborn8078d8c2012-03-20 11:11:26 -070066 /**
67 * Bitmap for thumbnail animation.
68 * @hide
69 */
70 public static final String KEY_ANIM_THUMBNAIL = "android:animThumbnail";
71
72 /**
73 * Start X position of thumbnail animation.
74 * @hide
75 */
76 public static final String KEY_ANIM_START_X = "android:animStartX";
77
78 /**
79 * Start Y position of thumbnail animation.
80 * @hide
81 */
82 public static final String KEY_ANIM_START_Y = "android:animStartY";
83
84 /**
Dianne Hackborneabfb3a2012-04-16 16:28:22 -070085 * Initial width of the animation.
86 * @hide
87 */
88 public static final String KEY_ANIM_START_WIDTH = "android:animStartWidth";
89
90 /**
91 * Initial height of the animation.
92 * @hide
93 */
94 public static final String KEY_ANIM_START_HEIGHT = "android:animStartHeight";
95
96 /**
Dianne Hackborn8078d8c2012-03-20 11:11:26 -070097 * Callback for when animation is started.
98 * @hide
99 */
100 public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
101
Adam Powell18e905f2013-10-24 14:27:48 -0700102 /**
Adam Powell18e905f2013-10-24 14:27:48 -0700103 * Arguments for the scene transition about to begin.
104 * @hide
105 */
106 public static final String KEY_SCENE_TRANSITION_ARGS = "android:sceneTransitionArgs";
107
George Mount0a778ed2013-12-13 13:35:36 -0800108 /**
109 * For Activity transitions, the calling Activity's TransitionListener used to
110 * notify the called Activity when the shared element and the exit transitions
111 * complete.
112 */
113 private static final String KEY_TRANSITION_COMPLETE_LISTENER
114 = "android:transitionCompleteListener";
115
116 /**
117 * For Activity transitions, the called Activity's listener to receive calls
118 * when transitions complete.
119 */
120 private static final String KEY_TRANSITION_TARGET_LISTENER = "android:transitionTargetListener";
121
122 /**
123 * The shared element's texture ID (TODO: not used yet).
124 */
125 private static final String KEY_SHARED_ELEMENT_TEXTURE_ID = "android:sharedElementTextureId";
126
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700127 /** @hide */
128 public static final int ANIM_NONE = 0;
129 /** @hide */
130 public static final int ANIM_CUSTOM = 1;
131 /** @hide */
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700132 public static final int ANIM_SCALE_UP = 2;
133 /** @hide */
Michael Jurka832cb222012-04-13 09:32:47 -0700134 public static final int ANIM_THUMBNAIL_SCALE_UP = 3;
Michael Jurka21385cd2012-05-03 10:57:31 -0700135 /** @hide */
Michael Jurka832cb222012-04-13 09:32:47 -0700136 public static final int ANIM_THUMBNAIL_SCALE_DOWN = 4;
Adam Powell18e905f2013-10-24 14:27:48 -0700137 /** @hide */
138 public static final int ANIM_SCENE_TRANSITION = 5;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700139
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700140 private String mPackageName;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700141 private int mAnimationType = ANIM_NONE;
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700142 private int mCustomEnterResId;
143 private int mCustomExitResId;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700144 private Bitmap mThumbnail;
145 private int mStartX;
146 private int mStartY;
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700147 private int mStartWidth;
148 private int mStartHeight;
Adam Powell18e905f2013-10-24 14:27:48 -0700149 private Bundle mTransitionArgs;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700150 private IRemoteCallback mAnimationStartedListener;
George Mount0a778ed2013-12-13 13:35:36 -0800151 private IRemoteCallback mTransitionCompleteListener;
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700152
153 /**
154 * Create an ActivityOptions specifying a custom animation to run when
155 * the activity is displayed.
156 *
157 * @param context Who is defining this. This is the application that the
158 * animation resources will be loaded from.
159 * @param enterResId A resource ID of the animation resource to use for
160 * the incoming activity. Use 0 for no animation.
161 * @param exitResId A resource ID of the animation resource to use for
162 * the outgoing activity. Use 0 for no animation.
163 * @return Returns a new ActivityOptions object that you can use to
164 * supply these options as the options Bundle when starting an activity.
165 */
166 public static ActivityOptions makeCustomAnimation(Context context,
167 int enterResId, int exitResId) {
Dianne Hackborn84375872012-06-01 19:03:50 -0700168 return makeCustomAnimation(context, enterResId, exitResId, null, null);
169 }
170
171 /**
172 * Create an ActivityOptions specifying a custom animation to run when
173 * the activity is displayed.
174 *
175 * @param context Who is defining this. This is the application that the
176 * animation resources will be loaded from.
177 * @param enterResId A resource ID of the animation resource to use for
178 * the incoming activity. Use 0 for no animation.
179 * @param exitResId A resource ID of the animation resource to use for
180 * the outgoing activity. Use 0 for no animation.
181 * @param handler If <var>listener</var> is non-null this must be a valid
182 * Handler on which to dispatch the callback; otherwise it should be null.
183 * @param listener Optional OnAnimationStartedListener to find out when the
184 * requested animation has started running. If for some reason the animation
185 * is not executed, the callback will happen immediately.
186 * @return Returns a new ActivityOptions object that you can use to
187 * supply these options as the options Bundle when starting an activity.
188 * @hide
189 */
190 public static ActivityOptions makeCustomAnimation(Context context,
191 int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) {
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700192 ActivityOptions opts = new ActivityOptions();
193 opts.mPackageName = context.getPackageName();
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700194 opts.mAnimationType = ANIM_CUSTOM;
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700195 opts.mCustomEnterResId = enterResId;
196 opts.mCustomExitResId = exitResId;
Adam Powell18e905f2013-10-24 14:27:48 -0700197 opts.setOnAnimationStartedListener(handler, listener);
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700198 return opts;
199 }
200
Adam Powell18e905f2013-10-24 14:27:48 -0700201 private void setOnAnimationStartedListener(Handler handler,
202 OnAnimationStartedListener listener) {
Dianne Hackborn84375872012-06-01 19:03:50 -0700203 if (listener != null) {
204 final Handler h = handler;
205 final OnAnimationStartedListener finalListener = listener;
206 mAnimationStartedListener = new IRemoteCallback.Stub() {
207 @Override public void sendResult(Bundle data) throws RemoteException {
208 h.post(new Runnable() {
209 @Override public void run() {
210 finalListener.onAnimationStarted();
211 }
212 });
213 }
214 };
215 }
216 }
217
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700218 /**
219 * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
220 * to find out when the given animation has started running.
Dianne Hackborn9944ecd2012-04-10 15:54:19 -0700221 * @hide
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700222 */
223 public interface OnAnimationStartedListener {
224 void onAnimationStarted();
225 }
226
George Mount0a778ed2013-12-13 13:35:36 -0800227 /** @hide */
228 public interface ActivityTransitionTarget {
229 void sharedElementTransitionComplete();
230 void exitTransitionComplete();
Adam Powell18e905f2013-10-24 14:27:48 -0700231 }
232
233 /**
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700234 * Create an ActivityOptions specifying an animation where the new
235 * activity is scaled from a small originating area of the screen to
236 * its final full representation.
237 *
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700238 * <p>If the Intent this is being used with has not set its
239 * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
240 * those bounds will be filled in for you based on the initial
241 * bounds passed in here.
242 *
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700243 * @param source The View that the new activity is animating from. This
244 * defines the coordinate space for <var>startX</var> and <var>startY</var>.
245 * @param startX The x starting location of the new activity, relative to <var>source</var>.
246 * @param startY The y starting location of the activity, relative to <var>source</var>.
247 * @param startWidth The initial width of the new activity.
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700248 * @param startHeight The initial height of the new activity.
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700249 * @return Returns a new ActivityOptions object that you can use to
250 * supply these options as the options Bundle when starting an activity.
251 */
252 public static ActivityOptions makeScaleUpAnimation(View source,
253 int startX, int startY, int startWidth, int startHeight) {
254 ActivityOptions opts = new ActivityOptions();
255 opts.mPackageName = source.getContext().getPackageName();
256 opts.mAnimationType = ANIM_SCALE_UP;
257 int[] pts = new int[2];
258 source.getLocationOnScreen(pts);
259 opts.mStartX = pts[0] + startX;
260 opts.mStartY = pts[1] + startY;
261 opts.mStartWidth = startWidth;
262 opts.mStartHeight = startHeight;
263 return opts;
264 }
265
266 /**
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700267 * Create an ActivityOptions specifying an animation where a thumbnail
268 * is scaled from a given position to the new activity window that is
269 * being started.
270 *
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700271 * <p>If the Intent this is being used with has not set its
272 * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
273 * those bounds will be filled in for you based on the initial
274 * thumbnail location and size provided here.
275 *
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700276 * @param source The View that this thumbnail is animating from. This
277 * defines the coordinate space for <var>startX</var> and <var>startY</var>.
278 * @param thumbnail The bitmap that will be shown as the initial thumbnail
279 * of the animation.
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700280 * @param startX The x starting location of the bitmap, relative to <var>source</var>.
281 * @param startY The y starting location of the bitmap, relative to <var>source</var>.
Dianne Hackborn9944ecd2012-04-10 15:54:19 -0700282 * @return Returns a new ActivityOptions object that you can use to
283 * supply these options as the options Bundle when starting an activity.
284 */
285 public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
286 Bitmap thumbnail, int startX, int startY) {
287 return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null);
288 }
289
290 /**
291 * Create an ActivityOptions specifying an animation where a thumbnail
292 * is scaled from a given position to the new activity window that is
293 * being started.
294 *
295 * @param source The View that this thumbnail is animating from. This
296 * defines the coordinate space for <var>startX</var> and <var>startY</var>.
297 * @param thumbnail The bitmap that will be shown as the initial thumbnail
298 * of the animation.
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700299 * @param startX The x starting location of the bitmap, relative to <var>source</var>.
300 * @param startY The y starting location of the bitmap, relative to <var>source</var>.
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700301 * @param listener Optional OnAnimationStartedListener to find out when the
302 * requested animation has started running. If for some reason the animation
303 * is not executed, the callback will happen immediately.
304 * @return Returns a new ActivityOptions object that you can use to
305 * supply these options as the options Bundle when starting an activity.
Dianne Hackborn9944ecd2012-04-10 15:54:19 -0700306 * @hide
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700307 */
308 public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
309 Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
Michael Jurka832cb222012-04-13 09:32:47 -0700310 return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true);
Michael Jurka21385cd2012-05-03 10:57:31 -0700311 }
312
313 /**
Michael Jurka832cb222012-04-13 09:32:47 -0700314 * Create an ActivityOptions specifying an animation where an activity window
315 * is scaled from a given position to a thumbnail at a specified location.
Michael Jurka21385cd2012-05-03 10:57:31 -0700316 *
Michael Jurka832cb222012-04-13 09:32:47 -0700317 * @param source The View that this thumbnail is animating to. This
Michael Jurka21385cd2012-05-03 10:57:31 -0700318 * defines the coordinate space for <var>startX</var> and <var>startY</var>.
Michael Jurka832cb222012-04-13 09:32:47 -0700319 * @param thumbnail The bitmap that will be shown as the final thumbnail
Michael Jurka21385cd2012-05-03 10:57:31 -0700320 * of the animation.
Michael Jurka832cb222012-04-13 09:32:47 -0700321 * @param startX The x end location of the bitmap, relative to <var>source</var>.
322 * @param startY The y end location of the bitmap, relative to <var>source</var>.
Michael Jurka21385cd2012-05-03 10:57:31 -0700323 * @param listener Optional OnAnimationStartedListener to find out when the
324 * requested animation has started running. If for some reason the animation
325 * is not executed, the callback will happen immediately.
326 * @return Returns a new ActivityOptions object that you can use to
327 * supply these options as the options Bundle when starting an activity.
328 * @hide
329 */
Michael Jurka832cb222012-04-13 09:32:47 -0700330 public static ActivityOptions makeThumbnailScaleDownAnimation(View source,
Michael Jurka21385cd2012-05-03 10:57:31 -0700331 Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
Michael Jurka832cb222012-04-13 09:32:47 -0700332 return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, false);
Michael Jurka21385cd2012-05-03 10:57:31 -0700333 }
334
Michael Jurka832cb222012-04-13 09:32:47 -0700335 private static ActivityOptions makeThumbnailAnimation(View source,
Michael Jurka21385cd2012-05-03 10:57:31 -0700336 Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
Michael Jurka832cb222012-04-13 09:32:47 -0700337 boolean scaleUp) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700338 ActivityOptions opts = new ActivityOptions();
339 opts.mPackageName = source.getContext().getPackageName();
Michael Jurka832cb222012-04-13 09:32:47 -0700340 opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700341 opts.mThumbnail = thumbnail;
342 int[] pts = new int[2];
343 source.getLocationOnScreen(pts);
344 opts.mStartX = pts[0] + startX;
345 opts.mStartY = pts[1] + startY;
Adam Powell18e905f2013-10-24 14:27:48 -0700346 opts.setOnAnimationStartedListener(source.getHandler(), listener);
347 return opts;
348 }
349
350 /**
George Mount0a778ed2013-12-13 13:35:36 -0800351 * Create an ActivityOptions to transition between Activities using cross-Activity animation.
352 * When visual elements are to carry between Activities, args should be used to tell the called
353 * Activity about the location and size.
Adam Powell18e905f2013-10-24 14:27:48 -0700354 *
George Mount0a778ed2013-12-13 13:35:36 -0800355 * TODO: Provide facility to capture layout and bitmap of shared elements.
356 *
357 * <p>When
358 * {@link android.app.Activity#startActivities(android.content.Intent[], android.os.Bundle)}
359 * is used with the {@link #toBundle()} result, the Activity's content scene will automatically
360 * transition out by setting their visibility to {@link View#INVISIBLE}. Shared elements
361 * ({@link android.view.View#setSharedElementName(String)}) are unmodified during the
362 * transition to allow the started Activity to seamlessly take it over. ViewGroups typically
363 * don't transition out, and instead transition out their children unless they have a
364 * background. To modify this behavior, use
365 * {@link android.view.ViewGroup#setTransitionGroup(boolean)}.</p>
366 *
367 * <p>This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be
368 * enabled on the calling Activity to cause an exit transition. The same must be in
369 * the called Activity to get an entering transition.</p>
370 *
371 * @param args Contains information for transferring a view between this Activity and the
372 * target Activity. Will be used by the called Activity to transition the
373 * view to its eventual destination
374 * @see android.app.Activity#startSharedElementTransition(android.os.Bundle)
Adam Powell18e905f2013-10-24 14:27:48 -0700375 */
George Mount0a778ed2013-12-13 13:35:36 -0800376 public static ActivityOptions makeSceneTransitionAnimation(Bundle args) {
Adam Powell18e905f2013-10-24 14:27:48 -0700377 ActivityOptions opts = new ActivityOptions();
378 opts.mAnimationType = ANIM_SCENE_TRANSITION;
Adam Powell18e905f2013-10-24 14:27:48 -0700379 opts.mTransitionArgs = args;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700380 return opts;
381 }
382
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700383 private ActivityOptions() {
384 }
385
386 /** @hide */
387 public ActivityOptions(Bundle opts) {
388 mPackageName = opts.getString(KEY_PACKAGE_NAME);
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700389 mAnimationType = opts.getInt(KEY_ANIM_TYPE);
Adam Powell18e905f2013-10-24 14:27:48 -0700390 switch (mAnimationType) {
391 case ANIM_CUSTOM:
392 mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
393 mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
394 mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
395 opts.getBinder(KEY_ANIM_START_LISTENER));
396 break;
397
398 case ANIM_SCALE_UP:
399 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
400 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
401 mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
402 mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
403 break;
404
405 case ANIM_THUMBNAIL_SCALE_UP:
406 case ANIM_THUMBNAIL_SCALE_DOWN:
407 mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
408 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
409 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
410 mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
411 opts.getBinder(KEY_ANIM_START_LISTENER));
412 break;
413
414 case ANIM_SCENE_TRANSITION:
Adam Powell18e905f2013-10-24 14:27:48 -0700415 mTransitionArgs = opts.getBundle(KEY_SCENE_TRANSITION_ARGS);
George Mount0a778ed2013-12-13 13:35:36 -0800416 mTransitionCompleteListener = IRemoteCallback.Stub.asInterface(
417 opts.getBinder(KEY_TRANSITION_COMPLETE_LISTENER));
Adam Powell18e905f2013-10-24 14:27:48 -0700418 break;
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700419 }
420 }
421
422 /** @hide */
423 public String getPackageName() {
424 return mPackageName;
425 }
426
427 /** @hide */
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700428 public int getAnimationType() {
429 return mAnimationType;
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700430 }
431
432 /** @hide */
433 public int getCustomEnterResId() {
434 return mCustomEnterResId;
435 }
436
437 /** @hide */
438 public int getCustomExitResId() {
439 return mCustomExitResId;
440 }
441
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700442 /** @hide */
443 public Bitmap getThumbnail() {
444 return mThumbnail;
445 }
446
447 /** @hide */
448 public int getStartX() {
449 return mStartX;
450 }
451
452 /** @hide */
453 public int getStartY() {
454 return mStartY;
455 }
456
457 /** @hide */
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700458 public int getStartWidth() {
459 return mStartWidth;
460 }
461
462 /** @hide */
463 public int getStartHeight() {
464 return mStartHeight;
465 }
466
467 /** @hide */
Adam Powell18e905f2013-10-24 14:27:48 -0700468 public Bundle getSceneTransitionArgs() {
469 return mTransitionArgs;
470 }
471
472 /** @hide */
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700473 public IRemoteCallback getOnAnimationStartListener() {
474 return mAnimationStartedListener;
475 }
476
477 /** @hide */
George Mount0a778ed2013-12-13 13:35:36 -0800478 public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target) {
479 boolean listenerSent = false;
480 if (mTransitionCompleteListener != null) {
481 IRemoteCallback callback = new IRemoteCallback.Stub() {
482 @Override
483 public void sendResult(Bundle data) throws RemoteException {
484 if (data == null) {
485 target.exitTransitionComplete();
486 } else {
487 // TODO: Use texture id
488 target.sharedElementTransitionComplete();
489 }
490 }
491 };
492 Bundle bundle = new Bundle();
493 bundle.putBinder(KEY_TRANSITION_TARGET_LISTENER, callback.asBinder());
Adam Powellcfbe9be2013-11-06 14:58:58 -0800494 try {
George Mount0a778ed2013-12-13 13:35:36 -0800495 mTransitionCompleteListener.sendResult(bundle);
496 listenerSent = true;
Adam Powellcfbe9be2013-11-06 14:58:58 -0800497 } catch (RemoteException e) {
George Mount0a778ed2013-12-13 13:35:36 -0800498 Log.w(TAG, "Couldn't retrieve transition notifications", e);
Adam Powellcfbe9be2013-11-06 14:58:58 -0800499 }
500 }
George Mount0a778ed2013-12-13 13:35:36 -0800501 if (!listenerSent) {
502 target.sharedElementTransitionComplete();
503 target.exitTransitionComplete();
504 }
Adam Powell18e905f2013-10-24 14:27:48 -0700505 }
506
507 /** @hide */
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700508 public void abort() {
509 if (mAnimationStartedListener != null) {
510 try {
511 mAnimationStartedListener.sendResult(null);
512 } catch (RemoteException e) {
513 }
514 }
515 }
516
517 /** @hide */
518 public static void abort(Bundle options) {
519 if (options != null) {
520 (new ActivityOptions(options)).abort();
521 }
522 }
523
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700524 /**
Dianne Hackbornddc52a82012-05-03 19:40:12 -0700525 * Update the current values in this ActivityOptions from those supplied
526 * in <var>otherOptions</var>. Any values
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700527 * defined in <var>otherOptions</var> replace those in the base options.
528 */
Dianne Hackbornddc52a82012-05-03 19:40:12 -0700529 public void update(ActivityOptions otherOptions) {
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700530 if (otherOptions.mPackageName != null) {
531 mPackageName = otherOptions.mPackageName;
532 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700533 switch (otherOptions.mAnimationType) {
534 case ANIM_CUSTOM:
535 mAnimationType = otherOptions.mAnimationType;
536 mCustomEnterResId = otherOptions.mCustomEnterResId;
537 mCustomExitResId = otherOptions.mCustomExitResId;
538 mThumbnail = null;
Adam Powell18e905f2013-10-24 14:27:48 -0700539 if (mAnimationStartedListener != null) {
Dianne Hackborn84375872012-06-01 19:03:50 -0700540 try {
Adam Powell18e905f2013-10-24 14:27:48 -0700541 mAnimationStartedListener.sendResult(null);
Dianne Hackborn84375872012-06-01 19:03:50 -0700542 } catch (RemoteException e) {
543 }
544 }
545 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
George Mount0a778ed2013-12-13 13:35:36 -0800546 mTransitionCompleteListener = null;
Adam Powell18e905f2013-10-24 14:27:48 -0700547 mTransitionArgs = null;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700548 break;
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700549 case ANIM_SCALE_UP:
550 mAnimationType = otherOptions.mAnimationType;
551 mStartX = otherOptions.mStartX;
552 mStartY = otherOptions.mStartY;
553 mStartWidth = otherOptions.mStartWidth;
554 mStartHeight = otherOptions.mStartHeight;
Adam Powell18e905f2013-10-24 14:27:48 -0700555 if (mAnimationStartedListener != null) {
Dianne Hackborn84375872012-06-01 19:03:50 -0700556 try {
Adam Powell18e905f2013-10-24 14:27:48 -0700557 mAnimationStartedListener.sendResult(null);
Dianne Hackborn84375872012-06-01 19:03:50 -0700558 } catch (RemoteException e) {
559 }
560 }
561 mAnimationStartedListener = null;
George Mount0a778ed2013-12-13 13:35:36 -0800562 mTransitionCompleteListener = null;
Adam Powell18e905f2013-10-24 14:27:48 -0700563 mTransitionArgs = null;
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700564 break;
Michael Jurka832cb222012-04-13 09:32:47 -0700565 case ANIM_THUMBNAIL_SCALE_UP:
566 case ANIM_THUMBNAIL_SCALE_DOWN:
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700567 mAnimationType = otherOptions.mAnimationType;
568 mThumbnail = otherOptions.mThumbnail;
569 mStartX = otherOptions.mStartX;
570 mStartY = otherOptions.mStartY;
Adam Powell18e905f2013-10-24 14:27:48 -0700571 if (mAnimationStartedListener != null) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700572 try {
Adam Powell18e905f2013-10-24 14:27:48 -0700573 mAnimationStartedListener.sendResult(null);
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700574 } catch (RemoteException e) {
575 }
576 }
577 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
George Mount0a778ed2013-12-13 13:35:36 -0800578 mTransitionCompleteListener = null;
Adam Powell18e905f2013-10-24 14:27:48 -0700579 mTransitionArgs = null;
Adam Powell18e905f2013-10-24 14:27:48 -0700580 break;
581 case ANIM_SCENE_TRANSITION:
582 mAnimationType = otherOptions.mAnimationType;
George Mount0a778ed2013-12-13 13:35:36 -0800583 mTransitionCompleteListener = otherOptions.mTransitionCompleteListener;
Adam Powellcfbe9be2013-11-06 14:58:58 -0800584 mTransitionArgs = otherOptions.mTransitionArgs;
585 mThumbnail = null;
Adam Powell18e905f2013-10-24 14:27:48 -0700586 mAnimationStartedListener = null;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700587 break;
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700588 }
589 }
590
591 /**
592 * Returns the created options as a Bundle, which can be passed to
593 * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
594 * Context.startActivity(Intent, Bundle)} and related methods.
595 * Note that the returned Bundle is still owned by the ActivityOptions
596 * object; you must not modify it, but can supply it to the startActivity
597 * methods that take an options Bundle.
598 */
599 public Bundle toBundle() {
600 Bundle b = new Bundle();
601 if (mPackageName != null) {
602 b.putString(KEY_PACKAGE_NAME, mPackageName);
603 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700604 switch (mAnimationType) {
605 case ANIM_CUSTOM:
606 b.putInt(KEY_ANIM_TYPE, mAnimationType);
607 b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
608 b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
Adam Powellcfbe9be2013-11-06 14:58:58 -0800609 b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
Dianne Hackborn84375872012-06-01 19:03:50 -0700610 != null ? mAnimationStartedListener.asBinder() : null);
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700611 break;
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700612 case ANIM_SCALE_UP:
613 b.putInt(KEY_ANIM_TYPE, mAnimationType);
614 b.putInt(KEY_ANIM_START_X, mStartX);
615 b.putInt(KEY_ANIM_START_Y, mStartY);
616 b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
617 b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
618 break;
Michael Jurka832cb222012-04-13 09:32:47 -0700619 case ANIM_THUMBNAIL_SCALE_UP:
620 case ANIM_THUMBNAIL_SCALE_DOWN:
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700621 b.putInt(KEY_ANIM_TYPE, mAnimationType);
622 b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
623 b.putInt(KEY_ANIM_START_X, mStartX);
624 b.putInt(KEY_ANIM_START_Y, mStartY);
Adam Powellcfbe9be2013-11-06 14:58:58 -0800625 b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700626 != null ? mAnimationStartedListener.asBinder() : null);
Dianne Hackborneabfb3a2012-04-16 16:28:22 -0700627 break;
Adam Powellcfbe9be2013-11-06 14:58:58 -0800628 case ANIM_SCENE_TRANSITION:
629 b.putInt(KEY_ANIM_TYPE, mAnimationType);
Adam Powellcfbe9be2013-11-06 14:58:58 -0800630 b.putBundle(KEY_SCENE_TRANSITION_ARGS, mTransitionArgs);
George Mount0a778ed2013-12-13 13:35:36 -0800631 if (mTransitionCompleteListener != null) {
632 b.putBinder(KEY_TRANSITION_COMPLETE_LISTENER,
633 mTransitionCompleteListener.asBinder());
634 }
Adam Powellcfbe9be2013-11-06 14:58:58 -0800635 break;
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700636 }
637 return b;
638 }
Adam Powellcfbe9be2013-11-06 14:58:58 -0800639
640 /**
641 * Return the filtered options only meant to be seen by the target activity itself
642 * @hide
643 */
644 public ActivityOptions forTargetActivity() {
645 if (mAnimationType == ANIM_SCENE_TRANSITION) {
646 final ActivityOptions result = new ActivityOptions();
647 result.update(this);
648 return result;
649 }
650
651 return null;
652 }
George Mount0a778ed2013-12-13 13:35:36 -0800653
654 /** @hide */
655 public interface SharedElementSource {
656 int getTextureId();
657 }
658
659 /**
660 * In the calling Activity when transitioning out, sets the Transition to listen for
661 * changes.
662 * @hide
663 */
664 public void setExitTransition(Transition transition, SharedElementSource sharedElementSource) {
665 mTransitionCompleteListener = new ExitTransitionListener(transition, sharedElementSource);
666 }
667
668 private static class ExitTransitionListener extends IRemoteCallback.Stub
669 implements Transition.TransitionListener, Animator.AnimatorListener {
670 private ArrayList<Animator> mSharedElementAnimators = new ArrayList<Animator>();
671 private boolean mSharedElementNotified;
672 private Transition mExitTransition;
673 private IRemoteCallback mTransitionCompleteCallback;
674 private boolean mExitComplete;
675 private SharedElementSource mSharedElementSource;
676
677 public ExitTransitionListener(Transition transition, SharedElementSource sharedElementSource) {
678 mSharedElementSource = sharedElementSource;
679 mExitTransition = transition;
680 mExitTransition.addListener(this);
681 }
682
683 @Override
684 public void sendResult(Bundle data) throws RemoteException {
685 if (data != null) {
686 mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface(
687 data.getBinder(KEY_TRANSITION_TARGET_LISTENER));
688 notifySharedElement();
689 notifyExit();
690 }
691 }
692
693 @Override
694 public void onTransitionStart(Transition transition) {
695 ArrayMap<Animator, Transition.AnimationInfo> runningAnimators
696 = Transition.getRunningAnimators();
697 for (Map.Entry<Animator, Transition.AnimationInfo> entry : runningAnimators.entrySet()) {
698 if (entry.getValue().view.getSharedElementName() != null) {
699 mSharedElementAnimators.add(entry.getKey());
700 entry.getKey().addListener(this);
701 }
702 }
703 notifySharedElement();
704 }
705
706 @Override
707 public void onTransitionEnd(Transition transition) {
708 mExitComplete = true;
709 notifyExit();
710 mExitTransition.removeListener(this);
711 }
712
713 @Override
714 public void onTransitionCancel(Transition transition) {
715 mExitComplete = true;
716 notifyExit();
717 mExitTransition.removeListener(this);
718 }
719
720 @Override
721 public void onTransitionPause(Transition transition) {
722 }
723
724 @Override
725 public void onTransitionResume(Transition transition) {
726 }
727
728 @Override
729 public void onAnimationStart(Animator animation) {
730 }
731
732 @Override
733 public void onAnimationEnd(Animator animation) {
734 mSharedElementAnimators.remove(animation);
735 notifySharedElement();
736 }
737
738 @Override
739 public void onAnimationCancel(Animator animation) {
740 mSharedElementAnimators.remove(animation);
741 notifySharedElement();
742 }
743
744 @Override
745 public void onAnimationRepeat(Animator animation) {
746 }
747
748 private void notifySharedElement() {
749 if (!mSharedElementNotified && mSharedElementAnimators.isEmpty()
750 && mTransitionCompleteCallback != null) {
751 mSharedElementNotified = true;
752 try {
753 Bundle bundle = new Bundle();
754 bundle.putInt(KEY_SHARED_ELEMENT_TEXTURE_ID, mSharedElementSource.getTextureId());
755 mTransitionCompleteCallback.sendResult(bundle);
756 } catch (RemoteException e) {
757 Log.w(TAG, "Couldn't notify that the transition ended", e);
758 }
759 }
760 }
761
762 private void notifyExit() {
763 if (mExitComplete && mTransitionCompleteCallback != null) {
764 try {
765 mTransitionCompleteCallback.sendResult(null);
766 } catch (RemoteException e) {
767 Log.w(TAG, "Couldn't notify that the transition ended", e);
768 }
769 }
770 }
771 }
Dianne Hackborn6de01a92012-03-19 19:07:40 -0700772}