ActivityOptions.java revision d367ca88eeede24e7d9a51ae85996a9d08d734b2
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
17package android.app;
18
19import android.content.Context;
20import android.graphics.Bitmap;
21import android.os.Bundle;
22import android.os.Handler;
23import android.os.IRemoteCallback;
24import android.os.RemoteException;
25import 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 */
32public 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
102    private String mPackageName;
103    private int mAnimationType = ANIM_NONE;
104    private int mCustomEnterResId;
105    private int mCustomExitResId;
106    private Bitmap mThumbnail;
107    private int mStartX;
108    private int mStartY;
109    private int mStartWidth;
110    private int mStartHeight;
111    private IRemoteCallback mAnimationStartedListener;
112
113    /**
114     * Create an ActivityOptions specifying a custom animation to run when
115     * the activity is displayed.
116     *
117     * @param context Who is defining this.  This is the application that the
118     * animation resources will be loaded from.
119     * @param enterResId A resource ID of the animation resource to use for
120     * the incoming activity.  Use 0 for no animation.
121     * @param exitResId A resource ID of the animation resource to use for
122     * the outgoing activity.  Use 0 for no animation.
123     * @return Returns a new ActivityOptions object that you can use to
124     * supply these options as the options Bundle when starting an activity.
125     */
126    public static ActivityOptions makeCustomAnimation(Context context,
127            int enterResId, int exitResId) {
128        ActivityOptions opts = new ActivityOptions();
129        opts.mPackageName = context.getPackageName();
130        opts.mAnimationType = ANIM_CUSTOM;
131        opts.mCustomEnterResId = enterResId;
132        opts.mCustomExitResId = exitResId;
133        return opts;
134    }
135
136    /**
137     * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
138     * to find out when the given animation has started running.
139     * @hide
140     */
141    public interface OnAnimationStartedListener {
142        void onAnimationStarted();
143    }
144
145    /**
146     * Create an ActivityOptions specifying an animation where the new
147     * activity is scaled from a small originating area of the screen to
148     * its final full representation.
149     *
150     * <p>If the Intent this is being used with has not set its
151     * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
152     * those bounds will be filled in for you based on the initial
153     * bounds passed in here.
154     *
155     * @param source The View that the new activity is animating from.  This
156     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
157     * @param startX The x starting location of the new activity, relative to <var>source</var>.
158     * @param startY The y starting location of the activity, relative to <var>source</var>.
159     * @param startWidth The initial width of the new activity.
160     * @param startHeight The initial height of the new activity.
161     * @return Returns a new ActivityOptions object that you can use to
162     * supply these options as the options Bundle when starting an activity.
163     */
164    public static ActivityOptions makeScaleUpAnimation(View source,
165            int startX, int startY, int startWidth, int startHeight) {
166        ActivityOptions opts = new ActivityOptions();
167        opts.mPackageName = source.getContext().getPackageName();
168        opts.mAnimationType = ANIM_SCALE_UP;
169        int[] pts = new int[2];
170        source.getLocationOnScreen(pts);
171        opts.mStartX = pts[0] + startX;
172        opts.mStartY = pts[1] + startY;
173        opts.mStartWidth = startWidth;
174        opts.mStartHeight = startHeight;
175        return opts;
176    }
177
178    /**
179     * Create an ActivityOptions specifying an animation where a thumbnail
180     * is scaled from a given position to the new activity window that is
181     * being started.
182     *
183     * <p>If the Intent this is being used with has not set its
184     * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
185     * those bounds will be filled in for you based on the initial
186     * thumbnail location and size provided here.
187     *
188     * @param source The View that this thumbnail is animating from.  This
189     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
190     * @param thumbnail The bitmap that will be shown as the initial thumbnail
191     * of the animation.
192     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
193     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
194     * @return Returns a new ActivityOptions object that you can use to
195     * supply these options as the options Bundle when starting an activity.
196     */
197    public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
198            Bitmap thumbnail, int startX, int startY) {
199        return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null);
200    }
201
202    /**
203     * Create an ActivityOptions specifying an animation where a thumbnail
204     * is scaled from a given position to the new activity window that is
205     * being started.
206     *
207     * @param source The View that this thumbnail is animating from.  This
208     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
209     * @param thumbnail The bitmap that will be shown as the initial thumbnail
210     * of the animation.
211     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
212     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
213     * @param listener Optional OnAnimationStartedListener to find out when the
214     * requested animation has started running.  If for some reason the animation
215     * is not executed, the callback will happen immediately.
216     * @return Returns a new ActivityOptions object that you can use to
217     * supply these options as the options Bundle when starting an activity.
218     * @hide
219     */
220    public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
221            Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
222        ActivityOptions opts = new ActivityOptions();
223        opts.mPackageName = source.getContext().getPackageName();
224        opts.mAnimationType = ANIM_THUMBNAIL;
225        opts.mThumbnail = thumbnail;
226        int[] pts = new int[2];
227        source.getLocationOnScreen(pts);
228        opts.mStartX = pts[0] + startX;
229        opts.mStartY = pts[1] + startY;
230        if (listener != null) {
231            final Handler h = source.getHandler();
232            final OnAnimationStartedListener finalListener = listener;
233            opts.mAnimationStartedListener = new IRemoteCallback.Stub() {
234                @Override public void sendResult(Bundle data) throws RemoteException {
235                    h.post(new Runnable() {
236                        @Override public void run() {
237                            finalListener.onAnimationStarted();
238                        }
239                    });
240                }
241            };
242        }
243        return opts;
244    }
245
246    private ActivityOptions() {
247    }
248
249    /** @hide */
250    public ActivityOptions(Bundle opts) {
251        mPackageName = opts.getString(KEY_PACKAGE_NAME);
252        mAnimationType = opts.getInt(KEY_ANIM_TYPE);
253        if (mAnimationType == ANIM_CUSTOM) {
254            mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
255            mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
256        } else if (mAnimationType == ANIM_SCALE_UP) {
257            mStartX = opts.getInt(KEY_ANIM_START_X, 0);
258            mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
259            mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
260            mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
261        } else if (mAnimationType == ANIM_THUMBNAIL) {
262            mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
263            mStartX = opts.getInt(KEY_ANIM_START_X, 0);
264            mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
265            mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
266                    opts.getIBinder(KEY_ANIM_START_LISTENER));
267        }
268    }
269
270    /** @hide */
271    public String getPackageName() {
272        return mPackageName;
273    }
274
275    /** @hide */
276    public int getAnimationType() {
277        return mAnimationType;
278    }
279
280    /** @hide */
281    public int getCustomEnterResId() {
282        return mCustomEnterResId;
283    }
284
285    /** @hide */
286    public int getCustomExitResId() {
287        return mCustomExitResId;
288    }
289
290    /** @hide */
291    public Bitmap getThumbnail() {
292        return mThumbnail;
293    }
294
295    /** @hide */
296    public int getStartX() {
297        return mStartX;
298    }
299
300    /** @hide */
301    public int getStartY() {
302        return mStartY;
303    }
304
305    /** @hide */
306    public int getStartWidth() {
307        return mStartWidth;
308    }
309
310    /** @hide */
311    public int getStartHeight() {
312        return mStartHeight;
313    }
314
315    /** @hide */
316    public IRemoteCallback getOnAnimationStartListener() {
317        return mAnimationStartedListener;
318    }
319
320    /** @hide */
321    public void abort() {
322        if (mAnimationStartedListener != null) {
323            try {
324                mAnimationStartedListener.sendResult(null);
325            } catch (RemoteException e) {
326            }
327        }
328    }
329
330    /** @hide */
331    public static void abort(Bundle options) {
332        if (options != null) {
333            (new ActivityOptions(options)).abort();
334        }
335    }
336
337    /**
338     * Update the current values in this ActivityOptions from those supplied
339     * in <var>otherOptions</var>.  Any values
340     * defined in <var>otherOptions</var> replace those in the base options.
341     */
342    public void update(ActivityOptions otherOptions) {
343        if (otherOptions.mPackageName != null) {
344            mPackageName = otherOptions.mPackageName;
345        }
346        switch (otherOptions.mAnimationType) {
347            case ANIM_CUSTOM:
348                mAnimationType = otherOptions.mAnimationType;
349                mCustomEnterResId = otherOptions.mCustomEnterResId;
350                mCustomExitResId = otherOptions.mCustomExitResId;
351                mThumbnail = null;
352                mAnimationStartedListener = null;
353                break;
354            case ANIM_SCALE_UP:
355                mAnimationType = otherOptions.mAnimationType;
356                mStartX = otherOptions.mStartX;
357                mStartY = otherOptions.mStartY;
358                mStartWidth = otherOptions.mStartWidth;
359                mStartHeight = otherOptions.mStartHeight;
360                break;
361            case ANIM_THUMBNAIL:
362                mAnimationType = otherOptions.mAnimationType;
363                mThumbnail = otherOptions.mThumbnail;
364                mStartX = otherOptions.mStartX;
365                mStartY = otherOptions.mStartY;
366                if (otherOptions.mAnimationStartedListener != null) {
367                    try {
368                        otherOptions.mAnimationStartedListener.sendResult(null);
369                    } catch (RemoteException e) {
370                    }
371                }
372                mAnimationStartedListener = otherOptions.mAnimationStartedListener;
373                break;
374        }
375    }
376
377    /**
378     * Returns the created options as a Bundle, which can be passed to
379     * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
380     * Context.startActivity(Intent, Bundle)} and related methods.
381     * Note that the returned Bundle is still owned by the ActivityOptions
382     * object; you must not modify it, but can supply it to the startActivity
383     * methods that take an options Bundle.
384     */
385    public Bundle toBundle() {
386        Bundle b = new Bundle();
387        if (mPackageName != null) {
388            b.putString(KEY_PACKAGE_NAME, mPackageName);
389        }
390        switch (mAnimationType) {
391            case ANIM_CUSTOM:
392                b.putInt(KEY_ANIM_TYPE, mAnimationType);
393                b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
394                b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
395                break;
396            case ANIM_SCALE_UP:
397                b.putInt(KEY_ANIM_TYPE, mAnimationType);
398                b.putInt(KEY_ANIM_START_X, mStartX);
399                b.putInt(KEY_ANIM_START_Y, mStartY);
400                b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
401                b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
402                break;
403            case ANIM_THUMBNAIL:
404                b.putInt(KEY_ANIM_TYPE, mAnimationType);
405                b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
406                b.putInt(KEY_ANIM_START_X, mStartX);
407                b.putInt(KEY_ANIM_START_Y, mStartY);
408                b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
409                        != null ? mAnimationStartedListener.asBinder() : null);
410                break;
411        }
412        return b;
413    }
414}
415