1 /* 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 17 package android.app; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.graphics.Bitmap; 22 import android.os.Bundle; 23 import android.os.Handler; 24 import android.os.IRemoteCallback; 25 import android.os.RemoteException; 26 import android.os.ResultReceiver; 27 import android.util.Pair; 28 import android.view.View; 29 import android.view.Window; 30 31 import java.util.ArrayList; 32 33 /** 34 * Helper class for building an options Bundle that can be used with 35 * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle) 36 * Context.startActivity(Intent, Bundle)} and related methods. 37 */ 38 public class ActivityOptions { 39 private static final String TAG = "ActivityOptions"; 40 41 /** 42 * The package name that created the options. 43 * @hide 44 */ 45 public static final String KEY_PACKAGE_NAME = "android:packageName"; 46 47 /** 48 * Type of animation that arguments specify. 49 * @hide 50 */ 51 public static final String KEY_ANIM_TYPE = "android:animType"; 52 53 /** 54 * Custom enter animation resource ID. 55 * @hide 56 */ 57 public static final String KEY_ANIM_ENTER_RES_ID = "android:animEnterRes"; 58 59 /** 60 * Custom exit animation resource ID. 61 * @hide 62 */ 63 public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes"; 64 65 /** 66 * Custom in-place animation resource ID. 67 * @hide 68 */ 69 public static final String KEY_ANIM_IN_PLACE_RES_ID = "android:animInPlaceRes"; 70 71 /** 72 * Bitmap for thumbnail animation. 73 * @hide 74 */ 75 public static final String KEY_ANIM_THUMBNAIL = "android:animThumbnail"; 76 77 /** 78 * Start X position of thumbnail animation. 79 * @hide 80 */ 81 public static final String KEY_ANIM_START_X = "android:animStartX"; 82 83 /** 84 * Start Y position of thumbnail animation. 85 * @hide 86 */ 87 public static final String KEY_ANIM_START_Y = "android:animStartY"; 88 89 /** 90 * Initial width of the animation. 91 * @hide 92 */ 93 public static final String KEY_ANIM_WIDTH = "android:animWidth"; 94 95 /** 96 * Initial height of the animation. 97 * @hide 98 */ 99 public static final String KEY_ANIM_HEIGHT = "android:animHeight"; 100 101 /** 102 * Callback for when animation is started. 103 * @hide 104 */ 105 public static final String KEY_ANIM_START_LISTENER = "android:animStartListener"; 106 107 /** 108 * For Activity transitions, the calling Activity's TransitionListener used to 109 * notify the called Activity when the shared element and the exit transitions 110 * complete. 111 */ 112 private static final String KEY_TRANSITION_COMPLETE_LISTENER 113 = "android:transitionCompleteListener"; 114 115 private static final String KEY_TRANSITION_IS_RETURNING = "android:transitionIsReturning"; 116 private static final String KEY_TRANSITION_SHARED_ELEMENTS = "android:sharedElementNames"; 117 private static final String KEY_RESULT_DATA = "android:resultData"; 118 private static final String KEY_RESULT_CODE = "android:resultCode"; 119 private static final String KEY_EXIT_COORDINATOR_INDEX = "android:exitCoordinatorIndex"; 120 121 /** @hide */ 122 public static final int ANIM_NONE = 0; 123 /** @hide */ 124 public static final int ANIM_CUSTOM = 1; 125 /** @hide */ 126 public static final int ANIM_SCALE_UP = 2; 127 /** @hide */ 128 public static final int ANIM_THUMBNAIL_SCALE_UP = 3; 129 /** @hide */ 130 public static final int ANIM_THUMBNAIL_SCALE_DOWN = 4; 131 /** @hide */ 132 public static final int ANIM_SCENE_TRANSITION = 5; 133 /** @hide */ 134 public static final int ANIM_DEFAULT = 6; 135 /** @hide */ 136 public static final int ANIM_LAUNCH_TASK_BEHIND = 7; 137 /** @hide */ 138 public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8; 139 /** @hide */ 140 public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9; 141 /** @hide */ 142 public static final int ANIM_CUSTOM_IN_PLACE = 10; 143 144 private String mPackageName; 145 private int mAnimationType = ANIM_NONE; 146 private int mCustomEnterResId; 147 private int mCustomExitResId; 148 private int mCustomInPlaceResId; 149 private Bitmap mThumbnail; 150 private int mStartX; 151 private int mStartY; 152 private int mWidth; 153 private int mHeight; 154 private IRemoteCallback mAnimationStartedListener; 155 private ResultReceiver mTransitionReceiver; 156 private boolean mIsReturning; 157 private ArrayList<String> mSharedElementNames; 158 private Intent mResultData; 159 private int mResultCode; 160 private int mExitCoordinatorIndex; 161 162 /** 163 * Create an ActivityOptions specifying a custom animation to run when 164 * the activity is displayed. 165 * 166 * @param context Who is defining this. This is the application that the 167 * animation resources will be loaded from. 168 * @param enterResId A resource ID of the animation resource to use for 169 * the incoming activity. Use 0 for no animation. 170 * @param exitResId A resource ID of the animation resource to use for 171 * the outgoing activity. Use 0 for no animation. 172 * @return Returns a new ActivityOptions object that you can use to 173 * supply these options as the options Bundle when starting an activity. 174 */ makeCustomAnimation(Context context, int enterResId, int exitResId)175 public static ActivityOptions makeCustomAnimation(Context context, 176 int enterResId, int exitResId) { 177 return makeCustomAnimation(context, enterResId, exitResId, null, null); 178 } 179 180 /** 181 * Create an ActivityOptions specifying a custom animation to run when 182 * the activity is displayed. 183 * 184 * @param context Who is defining this. This is the application that the 185 * animation resources will be loaded from. 186 * @param enterResId A resource ID of the animation resource to use for 187 * the incoming activity. Use 0 for no animation. 188 * @param exitResId A resource ID of the animation resource to use for 189 * the outgoing activity. Use 0 for no animation. 190 * @param handler If <var>listener</var> is non-null this must be a valid 191 * Handler on which to dispatch the callback; otherwise it should be null. 192 * @param listener Optional OnAnimationStartedListener to find out when the 193 * requested animation has started running. If for some reason the animation 194 * is not executed, the callback will happen immediately. 195 * @return Returns a new ActivityOptions object that you can use to 196 * supply these options as the options Bundle when starting an activity. 197 * @hide 198 */ makeCustomAnimation(Context context, int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener)199 public static ActivityOptions makeCustomAnimation(Context context, 200 int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) { 201 ActivityOptions opts = new ActivityOptions(); 202 opts.mPackageName = context.getPackageName(); 203 opts.mAnimationType = ANIM_CUSTOM; 204 opts.mCustomEnterResId = enterResId; 205 opts.mCustomExitResId = exitResId; 206 opts.setOnAnimationStartedListener(handler, listener); 207 return opts; 208 } 209 210 /** 211 * Creates an ActivityOptions specifying a custom animation to run in place on an existing 212 * activity. 213 * 214 * @param context Who is defining this. This is the application that the 215 * animation resources will be loaded from. 216 * @param animId A resource ID of the animation resource to use for 217 * the incoming activity. 218 * @return Returns a new ActivityOptions object that you can use to 219 * supply these options as the options Bundle when running an in-place animation. 220 * @hide 221 */ makeCustomInPlaceAnimation(Context context, int animId)222 public static ActivityOptions makeCustomInPlaceAnimation(Context context, int animId) { 223 if (animId == 0) { 224 throw new RuntimeException("You must specify a valid animation."); 225 } 226 227 ActivityOptions opts = new ActivityOptions(); 228 opts.mPackageName = context.getPackageName(); 229 opts.mAnimationType = ANIM_CUSTOM_IN_PLACE; 230 opts.mCustomInPlaceResId = animId; 231 return opts; 232 } 233 setOnAnimationStartedListener(Handler handler, OnAnimationStartedListener listener)234 private void setOnAnimationStartedListener(Handler handler, 235 OnAnimationStartedListener listener) { 236 if (listener != null) { 237 final Handler h = handler; 238 final OnAnimationStartedListener finalListener = listener; 239 mAnimationStartedListener = new IRemoteCallback.Stub() { 240 @Override public void sendResult(Bundle data) throws RemoteException { 241 h.post(new Runnable() { 242 @Override public void run() { 243 finalListener.onAnimationStarted(); 244 } 245 }); 246 } 247 }; 248 } 249 } 250 251 /** 252 * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation} 253 * to find out when the given animation has started running. 254 * @hide 255 */ 256 public interface OnAnimationStartedListener { onAnimationStarted()257 void onAnimationStarted(); 258 } 259 260 /** 261 * Create an ActivityOptions specifying an animation where the new 262 * activity is scaled from a small originating area of the screen to 263 * its final full representation. 264 * 265 * <p>If the Intent this is being used with has not set its 266 * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds}, 267 * those bounds will be filled in for you based on the initial 268 * bounds passed in here. 269 * 270 * @param source The View that the new activity is animating from. This 271 * defines the coordinate space for <var>startX</var> and <var>startY</var>. 272 * @param startX The x starting location of the new activity, relative to <var>source</var>. 273 * @param startY The y starting location of the activity, relative to <var>source</var>. 274 * @param width The initial width of the new activity. 275 * @param height The initial height of the new activity. 276 * @return Returns a new ActivityOptions object that you can use to 277 * supply these options as the options Bundle when starting an activity. 278 */ makeScaleUpAnimation(View source, int startX, int startY, int width, int height)279 public static ActivityOptions makeScaleUpAnimation(View source, 280 int startX, int startY, int width, int height) { 281 ActivityOptions opts = new ActivityOptions(); 282 opts.mPackageName = source.getContext().getPackageName(); 283 opts.mAnimationType = ANIM_SCALE_UP; 284 int[] pts = new int[2]; 285 source.getLocationOnScreen(pts); 286 opts.mStartX = pts[0] + startX; 287 opts.mStartY = pts[1] + startY; 288 opts.mWidth = width; 289 opts.mHeight = height; 290 return opts; 291 } 292 293 /** 294 * Create an ActivityOptions specifying an animation where a thumbnail 295 * is scaled from a given position to the new activity window that is 296 * being started. 297 * 298 * <p>If the Intent this is being used with has not set its 299 * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds}, 300 * those bounds will be filled in for you based on the initial 301 * thumbnail location and size provided here. 302 * 303 * @param source The View that this thumbnail is animating from. This 304 * defines the coordinate space for <var>startX</var> and <var>startY</var>. 305 * @param thumbnail The bitmap that will be shown as the initial thumbnail 306 * of the animation. 307 * @param startX The x starting location of the bitmap, relative to <var>source</var>. 308 * @param startY The y starting location of the bitmap, relative to <var>source</var>. 309 * @return Returns a new ActivityOptions object that you can use to 310 * supply these options as the options Bundle when starting an activity. 311 */ makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY)312 public static ActivityOptions makeThumbnailScaleUpAnimation(View source, 313 Bitmap thumbnail, int startX, int startY) { 314 return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null); 315 } 316 317 /** 318 * Create an ActivityOptions specifying an animation where a thumbnail 319 * is scaled from a given position to the new activity window that is 320 * being started. 321 * 322 * @param source The View that this thumbnail is animating from. This 323 * defines the coordinate space for <var>startX</var> and <var>startY</var>. 324 * @param thumbnail The bitmap that will be shown as the initial thumbnail 325 * of the animation. 326 * @param startX The x starting location of the bitmap, relative to <var>source</var>. 327 * @param startY The y starting location of the bitmap, relative to <var>source</var>. 328 * @param listener Optional OnAnimationStartedListener to find out when the 329 * requested animation has started running. If for some reason the animation 330 * is not executed, the callback will happen immediately. 331 * @return Returns a new ActivityOptions object that you can use to 332 * supply these options as the options Bundle when starting an activity. 333 * @hide 334 */ makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener)335 public static ActivityOptions makeThumbnailScaleUpAnimation(View source, 336 Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) { 337 return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true); 338 } 339 340 /** 341 * Create an ActivityOptions specifying an animation where an activity window 342 * is scaled from a given position to a thumbnail at a specified location. 343 * 344 * @param source The View that this thumbnail is animating to. This 345 * defines the coordinate space for <var>startX</var> and <var>startY</var>. 346 * @param thumbnail The bitmap that will be shown as the final thumbnail 347 * of the animation. 348 * @param startX The x end location of the bitmap, relative to <var>source</var>. 349 * @param startY The y end location of the bitmap, relative to <var>source</var>. 350 * @param listener Optional OnAnimationStartedListener to find out when the 351 * requested animation has started running. If for some reason the animation 352 * is not executed, the callback will happen immediately. 353 * @return Returns a new ActivityOptions object that you can use to 354 * supply these options as the options Bundle when starting an activity. 355 * @hide 356 */ makeThumbnailScaleDownAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener)357 public static ActivityOptions makeThumbnailScaleDownAnimation(View source, 358 Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) { 359 return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, false); 360 } 361 makeThumbnailAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp)362 private static ActivityOptions makeThumbnailAnimation(View source, 363 Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener, 364 boolean scaleUp) { 365 ActivityOptions opts = new ActivityOptions(); 366 opts.mPackageName = source.getContext().getPackageName(); 367 opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN; 368 opts.mThumbnail = thumbnail; 369 int[] pts = new int[2]; 370 source.getLocationOnScreen(pts); 371 opts.mStartX = pts[0] + startX; 372 opts.mStartY = pts[1] + startY; 373 opts.setOnAnimationStartedListener(source.getHandler(), listener); 374 return opts; 375 } 376 377 /** 378 * Create an ActivityOptions specifying an animation where the new activity 379 * window and a thumbnail is aspect-scaled to a new location. 380 * 381 * @param source The View that this thumbnail is animating from. This 382 * defines the coordinate space for <var>startX</var> and <var>startY</var>. 383 * @param thumbnail The bitmap that will be shown as the initial thumbnail 384 * of the animation. 385 * @param startX The x starting location of the bitmap, relative to <var>source</var>. 386 * @param startY The y starting location of the bitmap, relative to <var>source</var>. 387 * @param handler If <var>listener</var> is non-null this must be a valid 388 * Handler on which to dispatch the callback; otherwise it should be null. 389 * @param listener Optional OnAnimationStartedListener to find out when the 390 * requested animation has started running. If for some reason the animation 391 * is not executed, the callback will happen immediately. 392 * @return Returns a new ActivityOptions object that you can use to 393 * supply these options as the options Bundle when starting an activity. 394 * @hide 395 */ makeThumbnailAspectScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, Handler handler, OnAnimationStartedListener listener)396 public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source, 397 Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, 398 Handler handler, OnAnimationStartedListener listener) { 399 return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, 400 targetWidth, targetHeight, handler, listener, true); 401 } 402 403 /** 404 * Create an ActivityOptions specifying an animation where the new activity 405 * window and a thumbnail is aspect-scaled to a new location. 406 * 407 * @param source The View that this thumbnail is animating to. This 408 * defines the coordinate space for <var>startX</var> and <var>startY</var>. 409 * @param thumbnail The bitmap that will be shown as the final thumbnail 410 * of the animation. 411 * @param startX The x end location of the bitmap, relative to <var>source</var>. 412 * @param startY The y end location of the bitmap, relative to <var>source</var>. 413 * @param handler If <var>listener</var> is non-null this must be a valid 414 * Handler on which to dispatch the callback; otherwise it should be null. 415 * @param listener Optional OnAnimationStartedListener to find out when the 416 * requested animation has started running. If for some reason the animation 417 * is not executed, the callback will happen immediately. 418 * @return Returns a new ActivityOptions object that you can use to 419 * supply these options as the options Bundle when starting an activity. 420 * @hide 421 */ makeThumbnailAspectScaleDownAnimation(View source, Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, Handler handler, OnAnimationStartedListener listener)422 public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source, 423 Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, 424 Handler handler, OnAnimationStartedListener listener) { 425 return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, 426 targetWidth, targetHeight, handler, listener, false); 427 } 428 makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, Handler handler, OnAnimationStartedListener listener, boolean scaleUp)429 private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail, 430 int startX, int startY, int targetWidth, int targetHeight, 431 Handler handler, OnAnimationStartedListener listener, boolean scaleUp) { 432 ActivityOptions opts = new ActivityOptions(); 433 opts.mPackageName = source.getContext().getPackageName(); 434 opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP : 435 ANIM_THUMBNAIL_ASPECT_SCALE_DOWN; 436 opts.mThumbnail = thumbnail; 437 int[] pts = new int[2]; 438 source.getLocationOnScreen(pts); 439 opts.mStartX = pts[0] + startX; 440 opts.mStartY = pts[1] + startY; 441 opts.mWidth = targetWidth; 442 opts.mHeight = targetHeight; 443 opts.setOnAnimationStartedListener(handler, listener); 444 return opts; 445 } 446 447 /** 448 * Create an ActivityOptions to transition between Activities using cross-Activity scene 449 * animations. This method carries the position of one shared element to the started Activity. 450 * The position of <code>sharedElement</code> will be used as the epicenter for the 451 * exit Transition. The position of the shared element in the launched Activity will be the 452 * epicenter of its entering Transition. 453 * 454 * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be 455 * enabled on the calling Activity to cause an exit transition. The same must be in 456 * the called Activity to get an entering transition.</p> 457 * @param activity The Activity whose window contains the shared elements. 458 * @param sharedElement The View to transition to the started Activity. 459 * @param sharedElementName The shared element name as used in the target Activity. This 460 * must not be null. 461 * @return Returns a new ActivityOptions object that you can use to 462 * supply these options as the options Bundle when starting an activity. 463 * @see android.transition.Transition#setEpicenterCallback( 464 * android.transition.Transition.EpicenterCallback) 465 */ makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName)466 public static ActivityOptions makeSceneTransitionAnimation(Activity activity, 467 View sharedElement, String sharedElementName) { 468 return makeSceneTransitionAnimation(activity, Pair.create(sharedElement, sharedElementName)); 469 } 470 471 /** 472 * Create an ActivityOptions to transition between Activities using cross-Activity scene 473 * animations. This method carries the position of multiple shared elements to the started 474 * Activity. The position of the first element in sharedElements 475 * will be used as the epicenter for the exit Transition. The position of the associated 476 * shared element in the launched Activity will be the epicenter of its entering Transition. 477 * 478 * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be 479 * enabled on the calling Activity to cause an exit transition. The same must be in 480 * the called Activity to get an entering transition.</p> 481 * @param activity The Activity whose window contains the shared elements. 482 * @param sharedElements The names of the shared elements to transfer to the called 483 * Activity and their associated Views. The Views must each have 484 * a unique shared element name. 485 * @return Returns a new ActivityOptions object that you can use to 486 * supply these options as the options Bundle when starting an activity. 487 * @see android.transition.Transition#setEpicenterCallback( 488 * android.transition.Transition.EpicenterCallback) 489 */ makeSceneTransitionAnimation(Activity activity, Pair<View, String>... sharedElements)490 public static ActivityOptions makeSceneTransitionAnimation(Activity activity, 491 Pair<View, String>... sharedElements) { 492 ActivityOptions opts = new ActivityOptions(); 493 if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) { 494 opts.mAnimationType = ANIM_DEFAULT; 495 return opts; 496 } 497 opts.mAnimationType = ANIM_SCENE_TRANSITION; 498 499 ArrayList<String> names = new ArrayList<String>(); 500 ArrayList<View> views = new ArrayList<View>(); 501 502 if (sharedElements != null) { 503 for (int i = 0; i < sharedElements.length; i++) { 504 Pair<View, String> sharedElement = sharedElements[i]; 505 String sharedElementName = sharedElement.second; 506 if (sharedElementName == null) { 507 throw new IllegalArgumentException("Shared element name must not be null"); 508 } 509 names.add(sharedElementName); 510 View view = sharedElement.first; 511 if (view == null) { 512 throw new IllegalArgumentException("Shared element must not be null"); 513 } 514 views.add(sharedElement.first); 515 } 516 } 517 518 ExitTransitionCoordinator exit = new ExitTransitionCoordinator(activity, names, names, 519 views, false); 520 opts.mTransitionReceiver = exit; 521 opts.mSharedElementNames = names; 522 opts.mIsReturning = false; 523 opts.mExitCoordinatorIndex = 524 activity.mActivityTransitionState.addExitTransitionCoordinator(exit); 525 return opts; 526 } 527 528 /** @hide */ makeSceneTransitionAnimation(Activity activity, ExitTransitionCoordinator exitCoordinator, ArrayList<String> sharedElementNames, int resultCode, Intent resultData)529 public static ActivityOptions makeSceneTransitionAnimation(Activity activity, 530 ExitTransitionCoordinator exitCoordinator, ArrayList<String> sharedElementNames, 531 int resultCode, Intent resultData) { 532 ActivityOptions opts = new ActivityOptions(); 533 opts.mAnimationType = ANIM_SCENE_TRANSITION; 534 opts.mSharedElementNames = sharedElementNames; 535 opts.mTransitionReceiver = exitCoordinator; 536 opts.mIsReturning = true; 537 opts.mResultCode = resultCode; 538 opts.mResultData = resultData; 539 opts.mExitCoordinatorIndex = 540 activity.mActivityTransitionState.addExitTransitionCoordinator(exitCoordinator); 541 return opts; 542 } 543 544 /** 545 * If set along with Intent.FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be 546 * presented to the user but will instead be only available through the recents task list. 547 * In addition, the new task wil be affiliated with the launching activity's task. 548 * Affiliated tasks are grouped together in the recents task list. 549 * 550 * <p>This behavior is not supported for activities with {@link 551 * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of 552 * <code>singleInstance</code> or <code>singleTask</code>. 553 */ makeTaskLaunchBehind()554 public static ActivityOptions makeTaskLaunchBehind() { 555 final ActivityOptions opts = new ActivityOptions(); 556 opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND; 557 return opts; 558 } 559 560 /** @hide */ getLaunchTaskBehind()561 public boolean getLaunchTaskBehind() { 562 return mAnimationType == ANIM_LAUNCH_TASK_BEHIND; 563 } 564 ActivityOptions()565 private ActivityOptions() { 566 } 567 568 /** @hide */ ActivityOptions(Bundle opts)569 public ActivityOptions(Bundle opts) { 570 mPackageName = opts.getString(KEY_PACKAGE_NAME); 571 mAnimationType = opts.getInt(KEY_ANIM_TYPE); 572 switch (mAnimationType) { 573 case ANIM_CUSTOM: 574 mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0); 575 mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0); 576 mAnimationStartedListener = IRemoteCallback.Stub.asInterface( 577 opts.getBinder(KEY_ANIM_START_LISTENER)); 578 break; 579 580 case ANIM_CUSTOM_IN_PLACE: 581 mCustomInPlaceResId = opts.getInt(KEY_ANIM_IN_PLACE_RES_ID, 0); 582 break; 583 584 case ANIM_SCALE_UP: 585 mStartX = opts.getInt(KEY_ANIM_START_X, 0); 586 mStartY = opts.getInt(KEY_ANIM_START_Y, 0); 587 mWidth = opts.getInt(KEY_ANIM_WIDTH, 0); 588 mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0); 589 break; 590 591 case ANIM_THUMBNAIL_SCALE_UP: 592 case ANIM_THUMBNAIL_SCALE_DOWN: 593 case ANIM_THUMBNAIL_ASPECT_SCALE_UP: 594 case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: 595 mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL); 596 mStartX = opts.getInt(KEY_ANIM_START_X, 0); 597 mStartY = opts.getInt(KEY_ANIM_START_Y, 0); 598 mWidth = opts.getInt(KEY_ANIM_WIDTH, 0); 599 mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0); 600 mAnimationStartedListener = IRemoteCallback.Stub.asInterface( 601 opts.getBinder(KEY_ANIM_START_LISTENER)); 602 break; 603 604 case ANIM_SCENE_TRANSITION: 605 mTransitionReceiver = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER); 606 mIsReturning = opts.getBoolean(KEY_TRANSITION_IS_RETURNING, false); 607 mSharedElementNames = opts.getStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS); 608 mResultData = opts.getParcelable(KEY_RESULT_DATA); 609 mResultCode = opts.getInt(KEY_RESULT_CODE); 610 mExitCoordinatorIndex = opts.getInt(KEY_EXIT_COORDINATOR_INDEX); 611 break; 612 } 613 } 614 615 /** @hide */ getPackageName()616 public String getPackageName() { 617 return mPackageName; 618 } 619 620 /** @hide */ getAnimationType()621 public int getAnimationType() { 622 return mAnimationType; 623 } 624 625 /** @hide */ getCustomEnterResId()626 public int getCustomEnterResId() { 627 return mCustomEnterResId; 628 } 629 630 /** @hide */ getCustomExitResId()631 public int getCustomExitResId() { 632 return mCustomExitResId; 633 } 634 635 /** @hide */ getCustomInPlaceResId()636 public int getCustomInPlaceResId() { 637 return mCustomInPlaceResId; 638 } 639 640 /** @hide */ getThumbnail()641 public Bitmap getThumbnail() { 642 return mThumbnail; 643 } 644 645 /** @hide */ getStartX()646 public int getStartX() { 647 return mStartX; 648 } 649 650 /** @hide */ getStartY()651 public int getStartY() { 652 return mStartY; 653 } 654 655 /** @hide */ getWidth()656 public int getWidth() { 657 return mWidth; 658 } 659 660 /** @hide */ getHeight()661 public int getHeight() { 662 return mHeight; 663 } 664 665 /** @hide */ getOnAnimationStartListener()666 public IRemoteCallback getOnAnimationStartListener() { 667 return mAnimationStartedListener; 668 } 669 670 /** @hide */ getExitCoordinatorKey()671 public int getExitCoordinatorKey() { return mExitCoordinatorIndex; } 672 673 /** @hide */ abort()674 public void abort() { 675 if (mAnimationStartedListener != null) { 676 try { 677 mAnimationStartedListener.sendResult(null); 678 } catch (RemoteException e) { 679 } 680 } 681 } 682 683 /** @hide */ isReturning()684 public boolean isReturning() { 685 return mIsReturning; 686 } 687 688 /** @hide */ getSharedElementNames()689 public ArrayList<String> getSharedElementNames() { 690 return mSharedElementNames; 691 } 692 693 /** @hide */ getResultReceiver()694 public ResultReceiver getResultReceiver() { return mTransitionReceiver; } 695 696 /** @hide */ getResultCode()697 public int getResultCode() { return mResultCode; } 698 699 /** @hide */ getResultData()700 public Intent getResultData() { return mResultData; } 701 702 /** @hide */ abort(Bundle options)703 public static void abort(Bundle options) { 704 if (options != null) { 705 (new ActivityOptions(options)).abort(); 706 } 707 } 708 709 /** 710 * Update the current values in this ActivityOptions from those supplied 711 * in <var>otherOptions</var>. Any values 712 * defined in <var>otherOptions</var> replace those in the base options. 713 */ update(ActivityOptions otherOptions)714 public void update(ActivityOptions otherOptions) { 715 if (otherOptions.mPackageName != null) { 716 mPackageName = otherOptions.mPackageName; 717 } 718 mTransitionReceiver = null; 719 mSharedElementNames = null; 720 mIsReturning = false; 721 mResultData = null; 722 mResultCode = 0; 723 mExitCoordinatorIndex = 0; 724 mAnimationType = otherOptions.mAnimationType; 725 switch (otherOptions.mAnimationType) { 726 case ANIM_CUSTOM: 727 mCustomEnterResId = otherOptions.mCustomEnterResId; 728 mCustomExitResId = otherOptions.mCustomExitResId; 729 mThumbnail = null; 730 if (mAnimationStartedListener != null) { 731 try { 732 mAnimationStartedListener.sendResult(null); 733 } catch (RemoteException e) { 734 } 735 } 736 mAnimationStartedListener = otherOptions.mAnimationStartedListener; 737 break; 738 case ANIM_CUSTOM_IN_PLACE: 739 mCustomInPlaceResId = otherOptions.mCustomInPlaceResId; 740 break; 741 case ANIM_SCALE_UP: 742 mStartX = otherOptions.mStartX; 743 mStartY = otherOptions.mStartY; 744 mWidth = otherOptions.mWidth; 745 mHeight = otherOptions.mHeight; 746 if (mAnimationStartedListener != null) { 747 try { 748 mAnimationStartedListener.sendResult(null); 749 } catch (RemoteException e) { 750 } 751 } 752 mAnimationStartedListener = null; 753 break; 754 case ANIM_THUMBNAIL_SCALE_UP: 755 case ANIM_THUMBNAIL_SCALE_DOWN: 756 case ANIM_THUMBNAIL_ASPECT_SCALE_UP: 757 case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: 758 mThumbnail = otherOptions.mThumbnail; 759 mStartX = otherOptions.mStartX; 760 mStartY = otherOptions.mStartY; 761 mWidth = otherOptions.mWidth; 762 mHeight = otherOptions.mHeight; 763 if (mAnimationStartedListener != null) { 764 try { 765 mAnimationStartedListener.sendResult(null); 766 } catch (RemoteException e) { 767 } 768 } 769 mAnimationStartedListener = otherOptions.mAnimationStartedListener; 770 break; 771 case ANIM_SCENE_TRANSITION: 772 mTransitionReceiver = otherOptions.mTransitionReceiver; 773 mSharedElementNames = otherOptions.mSharedElementNames; 774 mIsReturning = otherOptions.mIsReturning; 775 mThumbnail = null; 776 mAnimationStartedListener = null; 777 mResultData = otherOptions.mResultData; 778 mResultCode = otherOptions.mResultCode; 779 mExitCoordinatorIndex = otherOptions.mExitCoordinatorIndex; 780 break; 781 } 782 } 783 784 /** 785 * Returns the created options as a Bundle, which can be passed to 786 * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle) 787 * Context.startActivity(Intent, Bundle)} and related methods. 788 * Note that the returned Bundle is still owned by the ActivityOptions 789 * object; you must not modify it, but can supply it to the startActivity 790 * methods that take an options Bundle. 791 */ toBundle()792 public Bundle toBundle() { 793 if (mAnimationType == ANIM_DEFAULT) { 794 return null; 795 } 796 Bundle b = new Bundle(); 797 if (mPackageName != null) { 798 b.putString(KEY_PACKAGE_NAME, mPackageName); 799 } 800 b.putInt(KEY_ANIM_TYPE, mAnimationType); 801 switch (mAnimationType) { 802 case ANIM_CUSTOM: 803 b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId); 804 b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId); 805 b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener 806 != null ? mAnimationStartedListener.asBinder() : null); 807 break; 808 case ANIM_CUSTOM_IN_PLACE: 809 b.putInt(KEY_ANIM_IN_PLACE_RES_ID, mCustomInPlaceResId); 810 break; 811 case ANIM_SCALE_UP: 812 b.putInt(KEY_ANIM_START_X, mStartX); 813 b.putInt(KEY_ANIM_START_Y, mStartY); 814 b.putInt(KEY_ANIM_WIDTH, mWidth); 815 b.putInt(KEY_ANIM_HEIGHT, mHeight); 816 break; 817 case ANIM_THUMBNAIL_SCALE_UP: 818 case ANIM_THUMBNAIL_SCALE_DOWN: 819 case ANIM_THUMBNAIL_ASPECT_SCALE_UP: 820 case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: 821 b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail); 822 b.putInt(KEY_ANIM_START_X, mStartX); 823 b.putInt(KEY_ANIM_START_Y, mStartY); 824 b.putInt(KEY_ANIM_WIDTH, mWidth); 825 b.putInt(KEY_ANIM_HEIGHT, mHeight); 826 b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener 827 != null ? mAnimationStartedListener.asBinder() : null); 828 break; 829 case ANIM_SCENE_TRANSITION: 830 if (mTransitionReceiver != null) { 831 b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionReceiver); 832 } 833 b.putBoolean(KEY_TRANSITION_IS_RETURNING, mIsReturning); 834 b.putStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS, mSharedElementNames); 835 b.putParcelable(KEY_RESULT_DATA, mResultData); 836 b.putInt(KEY_RESULT_CODE, mResultCode); 837 b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex); 838 break; 839 } 840 841 return b; 842 } 843 844 /** 845 * Return the filtered options only meant to be seen by the target activity itself 846 * @hide 847 */ forTargetActivity()848 public ActivityOptions forTargetActivity() { 849 if (mAnimationType == ANIM_SCENE_TRANSITION) { 850 final ActivityOptions result = new ActivityOptions(); 851 result.update(this); 852 return result; 853 } 854 855 return null; 856 } 857 858 } 859