• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.graphics.Bitmap;
21 import android.os.Bundle;
22 import android.os.Handler;
23 import android.os.IRemoteCallback;
24 import android.os.RemoteException;
25 import android.view.View;
26 
27 /**
28  * Helper class for building an options Bundle that can be used with
29  * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
30  * Context.startActivity(Intent, Bundle)} and related methods.
31  */
32 public class ActivityOptions {
33     /**
34      * The package name that created the options.
35      * @hide
36      */
37     public static final String KEY_PACKAGE_NAME = "android:packageName";
38 
39     /**
40      * Type of animation that arguments specify.
41      * @hide
42      */
43     public static final String KEY_ANIM_TYPE = "android:animType";
44 
45     /**
46      * Custom enter animation resource ID.
47      * @hide
48      */
49     public static final String KEY_ANIM_ENTER_RES_ID = "android:animEnterRes";
50 
51     /**
52      * Custom exit animation resource ID.
53      * @hide
54      */
55     public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes";
56 
57     /**
58      * Bitmap for thumbnail animation.
59      * @hide
60      */
61     public static final String KEY_ANIM_THUMBNAIL = "android:animThumbnail";
62 
63     /**
64      * Start X position of thumbnail animation.
65      * @hide
66      */
67     public static final String KEY_ANIM_START_X = "android:animStartX";
68 
69     /**
70      * Start Y position of thumbnail animation.
71      * @hide
72      */
73     public static final String KEY_ANIM_START_Y = "android:animStartY";
74 
75     /**
76      * Initial width of the animation.
77      * @hide
78      */
79     public static final String KEY_ANIM_START_WIDTH = "android:animStartWidth";
80 
81     /**
82      * Initial height of the animation.
83      * @hide
84      */
85     public static final String KEY_ANIM_START_HEIGHT = "android:animStartHeight";
86 
87     /**
88      * Callback for when animation is started.
89      * @hide
90      */
91     public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
92 
93     /** @hide */
94     public static final int ANIM_NONE = 0;
95     /** @hide */
96     public static final int ANIM_CUSTOM = 1;
97     /** @hide */
98     public static final int ANIM_SCALE_UP = 2;
99     /** @hide */
100     public static final int ANIM_THUMBNAIL = 3;
101     /** @hide */
102     public static final int ANIM_THUMBNAIL_DELAYED = 4;
103 
104     private String mPackageName;
105     private int mAnimationType = ANIM_NONE;
106     private int mCustomEnterResId;
107     private int mCustomExitResId;
108     private Bitmap mThumbnail;
109     private int mStartX;
110     private int mStartY;
111     private int mStartWidth;
112     private int mStartHeight;
113     private IRemoteCallback mAnimationStartedListener;
114 
115     /**
116      * Create an ActivityOptions specifying a custom animation to run when
117      * the activity is displayed.
118      *
119      * @param context Who is defining this.  This is the application that the
120      * animation resources will be loaded from.
121      * @param enterResId A resource ID of the animation resource to use for
122      * the incoming activity.  Use 0 for no animation.
123      * @param exitResId A resource ID of the animation resource to use for
124      * the outgoing activity.  Use 0 for no animation.
125      * @return Returns a new ActivityOptions object that you can use to
126      * supply these options as the options Bundle when starting an activity.
127      */
makeCustomAnimation(Context context, int enterResId, int exitResId)128     public static ActivityOptions makeCustomAnimation(Context context,
129             int enterResId, int exitResId) {
130         return makeCustomAnimation(context, enterResId, exitResId, null, null);
131     }
132 
133     /**
134      * Create an ActivityOptions specifying a custom animation to run when
135      * the activity is displayed.
136      *
137      * @param context Who is defining this.  This is the application that the
138      * animation resources will be loaded from.
139      * @param enterResId A resource ID of the animation resource to use for
140      * the incoming activity.  Use 0 for no animation.
141      * @param exitResId A resource ID of the animation resource to use for
142      * the outgoing activity.  Use 0 for no animation.
143      * @param handler If <var>listener</var> is non-null this must be a valid
144      * Handler on which to dispatch the callback; otherwise it should be null.
145      * @param listener Optional OnAnimationStartedListener to find out when the
146      * requested animation has started running.  If for some reason the animation
147      * is not executed, the callback will happen immediately.
148      * @return Returns a new ActivityOptions object that you can use to
149      * supply these options as the options Bundle when starting an activity.
150      * @hide
151      */
makeCustomAnimation(Context context, int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener)152     public static ActivityOptions makeCustomAnimation(Context context,
153             int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) {
154         ActivityOptions opts = new ActivityOptions();
155         opts.mPackageName = context.getPackageName();
156         opts.mAnimationType = ANIM_CUSTOM;
157         opts.mCustomEnterResId = enterResId;
158         opts.mCustomExitResId = exitResId;
159         opts.setListener(handler, listener);
160         return opts;
161     }
162 
setListener(Handler handler, OnAnimationStartedListener listener)163     private void setListener(Handler handler, OnAnimationStartedListener listener) {
164         if (listener != null) {
165             final Handler h = handler;
166             final OnAnimationStartedListener finalListener = listener;
167             mAnimationStartedListener = new IRemoteCallback.Stub() {
168                 @Override public void sendResult(Bundle data) throws RemoteException {
169                     h.post(new Runnable() {
170                         @Override public void run() {
171                             finalListener.onAnimationStarted();
172                         }
173                     });
174                 }
175             };
176         }
177     }
178 
179     /**
180      * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
181      * to find out when the given animation has started running.
182      * @hide
183      */
184     public interface OnAnimationStartedListener {
onAnimationStarted()185         void onAnimationStarted();
186     }
187 
188     /**
189      * Create an ActivityOptions specifying an animation where the new
190      * activity is scaled from a small originating area of the screen to
191      * its final full representation.
192      *
193      * <p>If the Intent this is being used with has not set its
194      * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
195      * those bounds will be filled in for you based on the initial
196      * bounds passed in here.
197      *
198      * @param source The View that the new activity is animating from.  This
199      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
200      * @param startX The x starting location of the new activity, relative to <var>source</var>.
201      * @param startY The y starting location of the activity, relative to <var>source</var>.
202      * @param startWidth The initial width of the new activity.
203      * @param startHeight The initial height of the new activity.
204      * @return Returns a new ActivityOptions object that you can use to
205      * supply these options as the options Bundle when starting an activity.
206      */
makeScaleUpAnimation(View source, int startX, int startY, int startWidth, int startHeight)207     public static ActivityOptions makeScaleUpAnimation(View source,
208             int startX, int startY, int startWidth, int startHeight) {
209         ActivityOptions opts = new ActivityOptions();
210         opts.mPackageName = source.getContext().getPackageName();
211         opts.mAnimationType = ANIM_SCALE_UP;
212         int[] pts = new int[2];
213         source.getLocationOnScreen(pts);
214         opts.mStartX = pts[0] + startX;
215         opts.mStartY = pts[1] + startY;
216         opts.mStartWidth = startWidth;
217         opts.mStartHeight = startHeight;
218         return opts;
219     }
220 
221     /**
222      * Create an ActivityOptions specifying an animation where a thumbnail
223      * is scaled from a given position to the new activity window that is
224      * being started.
225      *
226      * <p>If the Intent this is being used with has not set its
227      * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
228      * those bounds will be filled in for you based on the initial
229      * thumbnail location and size provided here.
230      *
231      * @param source The View that this thumbnail is animating from.  This
232      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
233      * @param thumbnail The bitmap that will be shown as the initial thumbnail
234      * of the animation.
235      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
236      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
237      * @return Returns a new ActivityOptions object that you can use to
238      * supply these options as the options Bundle when starting an activity.
239      */
makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY)240     public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
241             Bitmap thumbnail, int startX, int startY) {
242         return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null);
243     }
244 
245     /**
246      * Create an ActivityOptions specifying an animation where a thumbnail
247      * is scaled from a given position to the new activity window that is
248      * being started.
249      *
250      * @param source The View that this thumbnail is animating from.  This
251      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
252      * @param thumbnail The bitmap that will be shown as the initial thumbnail
253      * of the animation.
254      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
255      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
256      * @param listener Optional OnAnimationStartedListener to find out when the
257      * requested animation has started running.  If for some reason the animation
258      * is not executed, the callback will happen immediately.
259      * @return Returns a new ActivityOptions object that you can use to
260      * supply these options as the options Bundle when starting an activity.
261      * @hide
262      */
makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener)263     public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
264             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
265         return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, listener, false);
266     }
267 
268     /**
269      * Create an ActivityOptions specifying an animation where a thumbnail
270      * is scaled from a given position to the new activity window that is
271      * being started. Before the animation, there is a short delay.
272      *
273      * @param source The View that this thumbnail is animating from.  This
274      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
275      * @param thumbnail The bitmap that will be shown as the initial thumbnail
276      * of the animation.
277      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
278      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
279      * @param listener Optional OnAnimationStartedListener to find out when the
280      * requested animation has started running.  If for some reason the animation
281      * is not executed, the callback will happen immediately.
282      * @return Returns a new ActivityOptions object that you can use to
283      * supply these options as the options Bundle when starting an activity.
284      * @hide
285      */
makeDelayedThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener)286     public static ActivityOptions makeDelayedThumbnailScaleUpAnimation(View source,
287             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
288         return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, listener, true);
289     }
290 
makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener, boolean delayed)291     private static ActivityOptions makeThumbnailScaleUpAnimation(View source,
292             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
293             boolean delayed) {
294         ActivityOptions opts = new ActivityOptions();
295         opts.mPackageName = source.getContext().getPackageName();
296         opts.mAnimationType = delayed ? ANIM_THUMBNAIL_DELAYED : ANIM_THUMBNAIL;
297         opts.mThumbnail = thumbnail;
298         int[] pts = new int[2];
299         source.getLocationOnScreen(pts);
300         opts.mStartX = pts[0] + startX;
301         opts.mStartY = pts[1] + startY;
302         opts.setListener(source.getHandler(), listener);
303         return opts;
304     }
305 
ActivityOptions()306     private ActivityOptions() {
307     }
308 
309     /** @hide */
ActivityOptions(Bundle opts)310     public ActivityOptions(Bundle opts) {
311         mPackageName = opts.getString(KEY_PACKAGE_NAME);
312         mAnimationType = opts.getInt(KEY_ANIM_TYPE);
313         if (mAnimationType == ANIM_CUSTOM) {
314             mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
315             mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
316             mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
317                     opts.getIBinder(KEY_ANIM_START_LISTENER));
318         } else if (mAnimationType == ANIM_SCALE_UP) {
319             mStartX = opts.getInt(KEY_ANIM_START_X, 0);
320             mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
321             mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
322             mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
323         } else if (mAnimationType == ANIM_THUMBNAIL ||
324                 mAnimationType == ANIM_THUMBNAIL_DELAYED) {
325             mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
326             mStartX = opts.getInt(KEY_ANIM_START_X, 0);
327             mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
328             mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
329                     opts.getIBinder(KEY_ANIM_START_LISTENER));
330         }
331     }
332 
333     /** @hide */
getPackageName()334     public String getPackageName() {
335         return mPackageName;
336     }
337 
338     /** @hide */
getAnimationType()339     public int getAnimationType() {
340         return mAnimationType;
341     }
342 
343     /** @hide */
getCustomEnterResId()344     public int getCustomEnterResId() {
345         return mCustomEnterResId;
346     }
347 
348     /** @hide */
getCustomExitResId()349     public int getCustomExitResId() {
350         return mCustomExitResId;
351     }
352 
353     /** @hide */
getThumbnail()354     public Bitmap getThumbnail() {
355         return mThumbnail;
356     }
357 
358     /** @hide */
getStartX()359     public int getStartX() {
360         return mStartX;
361     }
362 
363     /** @hide */
getStartY()364     public int getStartY() {
365         return mStartY;
366     }
367 
368     /** @hide */
getStartWidth()369     public int getStartWidth() {
370         return mStartWidth;
371     }
372 
373     /** @hide */
getStartHeight()374     public int getStartHeight() {
375         return mStartHeight;
376     }
377 
378     /** @hide */
getOnAnimationStartListener()379     public IRemoteCallback getOnAnimationStartListener() {
380         return mAnimationStartedListener;
381     }
382 
383     /** @hide */
abort()384     public void abort() {
385         if (mAnimationStartedListener != null) {
386             try {
387                 mAnimationStartedListener.sendResult(null);
388             } catch (RemoteException e) {
389             }
390         }
391     }
392 
393     /** @hide */
abort(Bundle options)394     public static void abort(Bundle options) {
395         if (options != null) {
396             (new ActivityOptions(options)).abort();
397         }
398     }
399 
400     /**
401      * Update the current values in this ActivityOptions from those supplied
402      * in <var>otherOptions</var>.  Any values
403      * defined in <var>otherOptions</var> replace those in the base options.
404      */
update(ActivityOptions otherOptions)405     public void update(ActivityOptions otherOptions) {
406         if (otherOptions.mPackageName != null) {
407             mPackageName = otherOptions.mPackageName;
408         }
409         switch (otherOptions.mAnimationType) {
410             case ANIM_CUSTOM:
411                 mAnimationType = otherOptions.mAnimationType;
412                 mCustomEnterResId = otherOptions.mCustomEnterResId;
413                 mCustomExitResId = otherOptions.mCustomExitResId;
414                 mThumbnail = null;
415                 if (otherOptions.mAnimationStartedListener != null) {
416                     try {
417                         otherOptions.mAnimationStartedListener.sendResult(null);
418                     } catch (RemoteException e) {
419                     }
420                 }
421                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
422                 break;
423             case ANIM_SCALE_UP:
424                 mAnimationType = otherOptions.mAnimationType;
425                 mStartX = otherOptions.mStartX;
426                 mStartY = otherOptions.mStartY;
427                 mStartWidth = otherOptions.mStartWidth;
428                 mStartHeight = otherOptions.mStartHeight;
429                 if (otherOptions.mAnimationStartedListener != null) {
430                     try {
431                         otherOptions.mAnimationStartedListener.sendResult(null);
432                     } catch (RemoteException e) {
433                     }
434                 }
435                 mAnimationStartedListener = null;
436                 break;
437             case ANIM_THUMBNAIL:
438             case ANIM_THUMBNAIL_DELAYED:
439                 mAnimationType = otherOptions.mAnimationType;
440                 mThumbnail = otherOptions.mThumbnail;
441                 mStartX = otherOptions.mStartX;
442                 mStartY = otherOptions.mStartY;
443                 if (otherOptions.mAnimationStartedListener != null) {
444                     try {
445                         otherOptions.mAnimationStartedListener.sendResult(null);
446                     } catch (RemoteException e) {
447                     }
448                 }
449                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
450                 break;
451         }
452     }
453 
454     /**
455      * Returns the created options as a Bundle, which can be passed to
456      * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
457      * Context.startActivity(Intent, Bundle)} and related methods.
458      * Note that the returned Bundle is still owned by the ActivityOptions
459      * object; you must not modify it, but can supply it to the startActivity
460      * methods that take an options Bundle.
461      */
toBundle()462     public Bundle toBundle() {
463         Bundle b = new Bundle();
464         if (mPackageName != null) {
465             b.putString(KEY_PACKAGE_NAME, mPackageName);
466         }
467         switch (mAnimationType) {
468             case ANIM_CUSTOM:
469                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
470                 b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
471                 b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
472                 b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
473                         != null ? mAnimationStartedListener.asBinder() : null);
474                 break;
475             case ANIM_SCALE_UP:
476                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
477                 b.putInt(KEY_ANIM_START_X, mStartX);
478                 b.putInt(KEY_ANIM_START_Y, mStartY);
479                 b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
480                 b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
481                 break;
482             case ANIM_THUMBNAIL:
483             case ANIM_THUMBNAIL_DELAYED:
484                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
485                 b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
486                 b.putInt(KEY_ANIM_START_X, mStartX);
487                 b.putInt(KEY_ANIM_START_Y, mStartY);
488                 b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
489                         != null ? mAnimationStartedListener.asBinder() : null);
490                 break;
491         }
492         return b;
493     }
494 }
495