ActivityOptions.java revision eabfb3a36e9469c5e219f92b39b7200104319185
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     * @param source The View that the new activity is animating from.  This
151     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
152     * @param startX The x starting location of the new activity, relative to <var>source</var>.
153     * @param startY The y starting location of the activity, relative to <var>source</var>.
154     * @param startWidth The initial width of the new activity.
155     * @param startWidth The initial height of the new activity.
156     * @return Returns a new ActivityOptions object that you can use to
157     * supply these options as the options Bundle when starting an activity.
158     */
159    public static ActivityOptions makeScaleUpAnimation(View source,
160            int startX, int startY, int startWidth, int startHeight) {
161        ActivityOptions opts = new ActivityOptions();
162        opts.mPackageName = source.getContext().getPackageName();
163        opts.mAnimationType = ANIM_SCALE_UP;
164        int[] pts = new int[2];
165        source.getLocationOnScreen(pts);
166        opts.mStartX = pts[0] + startX;
167        opts.mStartY = pts[1] + startY;
168        opts.mStartWidth = startWidth;
169        opts.mStartHeight = startHeight;
170        return opts;
171    }
172
173    /**
174     * Create an ActivityOptions specifying an animation where a thumbnail
175     * is scaled from a given position to the new activity window that is
176     * being started.
177     *
178     * @param source The View that this thumbnail is animating from.  This
179     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
180     * @param thumbnail The bitmap that will be shown as the initial thumbnail
181     * of the animation.
182     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
183     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
184     * @return Returns a new ActivityOptions object that you can use to
185     * supply these options as the options Bundle when starting an activity.
186     */
187    public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
188            Bitmap thumbnail, int startX, int startY) {
189        return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null);
190    }
191
192    /**
193     * Create an ActivityOptions specifying an animation where a thumbnail
194     * is scaled from a given position to the new activity window that is
195     * being started.
196     *
197     * @param source The View that this thumbnail is animating from.  This
198     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
199     * @param thumbnail The bitmap that will be shown as the initial thumbnail
200     * of the animation.
201     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
202     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
203     * @param listener Optional OnAnimationStartedListener to find out when the
204     * requested animation has started running.  If for some reason the animation
205     * is not executed, the callback will happen immediately.
206     * @return Returns a new ActivityOptions object that you can use to
207     * supply these options as the options Bundle when starting an activity.
208     * @hide
209     */
210    public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
211            Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
212        ActivityOptions opts = new ActivityOptions();
213        opts.mPackageName = source.getContext().getPackageName();
214        opts.mAnimationType = ANIM_THUMBNAIL;
215        opts.mThumbnail = thumbnail;
216        int[] pts = new int[2];
217        source.getLocationOnScreen(pts);
218        opts.mStartX = pts[0] + startX;
219        opts.mStartY = pts[1] + startY;
220        if (listener != null) {
221            final Handler h = source.getHandler();
222            final OnAnimationStartedListener finalListener = listener;
223            opts.mAnimationStartedListener = new IRemoteCallback.Stub() {
224                @Override public void sendResult(Bundle data) throws RemoteException {
225                    h.post(new Runnable() {
226                        @Override public void run() {
227                            finalListener.onAnimationStarted();
228                        }
229                    });
230                }
231            };
232        }
233        return opts;
234    }
235
236    private ActivityOptions() {
237    }
238
239    /** @hide */
240    public ActivityOptions(Bundle opts) {
241        mPackageName = opts.getString(KEY_PACKAGE_NAME);
242        mAnimationType = opts.getInt(KEY_ANIM_TYPE);
243        if (mAnimationType == ANIM_CUSTOM) {
244            mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
245            mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
246        } else if (mAnimationType == ANIM_SCALE_UP) {
247            mStartX = opts.getInt(KEY_ANIM_START_X, 0);
248            mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
249            mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
250            mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
251        } else if (mAnimationType == ANIM_THUMBNAIL) {
252            mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
253            mStartX = opts.getInt(KEY_ANIM_START_X, 0);
254            mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
255            mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
256                    opts.getIBinder(KEY_ANIM_START_LISTENER));
257        }
258    }
259
260    /** @hide */
261    public String getPackageName() {
262        return mPackageName;
263    }
264
265    /** @hide */
266    public int getAnimationType() {
267        return mAnimationType;
268    }
269
270    /** @hide */
271    public int getCustomEnterResId() {
272        return mCustomEnterResId;
273    }
274
275    /** @hide */
276    public int getCustomExitResId() {
277        return mCustomExitResId;
278    }
279
280    /** @hide */
281    public Bitmap getThumbnail() {
282        return mThumbnail;
283    }
284
285    /** @hide */
286    public int getStartX() {
287        return mStartX;
288    }
289
290    /** @hide */
291    public int getStartY() {
292        return mStartY;
293    }
294
295    /** @hide */
296    public int getStartWidth() {
297        return mStartWidth;
298    }
299
300    /** @hide */
301    public int getStartHeight() {
302        return mStartHeight;
303    }
304
305    /** @hide */
306    public IRemoteCallback getOnAnimationStartListener() {
307        return mAnimationStartedListener;
308    }
309
310    /** @hide */
311    public void abort() {
312        if (mAnimationStartedListener != null) {
313            try {
314                mAnimationStartedListener.sendResult(null);
315            } catch (RemoteException e) {
316            }
317        }
318    }
319
320    /** @hide */
321    public static void abort(Bundle options) {
322        if (options != null) {
323            (new ActivityOptions(options)).abort();
324        }
325    }
326
327    /**
328     * Join the values in <var>otherOptions</var> in to this one.  Any values
329     * defined in <var>otherOptions</var> replace those in the base options.
330     */
331    public void join(ActivityOptions otherOptions) {
332        if (otherOptions.mPackageName != null) {
333            mPackageName = otherOptions.mPackageName;
334        }
335        switch (otherOptions.mAnimationType) {
336            case ANIM_CUSTOM:
337                mAnimationType = otherOptions.mAnimationType;
338                mCustomEnterResId = otherOptions.mCustomEnterResId;
339                mCustomExitResId = otherOptions.mCustomExitResId;
340                mThumbnail = null;
341                mAnimationStartedListener = null;
342                break;
343            case ANIM_SCALE_UP:
344                mAnimationType = otherOptions.mAnimationType;
345                mStartX = otherOptions.mStartX;
346                mStartY = otherOptions.mStartY;
347                mStartWidth = otherOptions.mStartWidth;
348                mStartHeight = otherOptions.mStartHeight;
349                break;
350            case ANIM_THUMBNAIL:
351                mAnimationType = otherOptions.mAnimationType;
352                mThumbnail = otherOptions.mThumbnail;
353                mStartX = otherOptions.mStartX;
354                mStartY = otherOptions.mStartY;
355                if (otherOptions.mAnimationStartedListener != null) {
356                    try {
357                        otherOptions.mAnimationStartedListener.sendResult(null);
358                    } catch (RemoteException e) {
359                    }
360                }
361                mAnimationStartedListener = otherOptions.mAnimationStartedListener;
362                break;
363        }
364    }
365
366    /**
367     * Returns the created options as a Bundle, which can be passed to
368     * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
369     * Context.startActivity(Intent, Bundle)} and related methods.
370     * Note that the returned Bundle is still owned by the ActivityOptions
371     * object; you must not modify it, but can supply it to the startActivity
372     * methods that take an options Bundle.
373     */
374    public Bundle toBundle() {
375        Bundle b = new Bundle();
376        if (mPackageName != null) {
377            b.putString(KEY_PACKAGE_NAME, mPackageName);
378        }
379        switch (mAnimationType) {
380            case ANIM_CUSTOM:
381                b.putInt(KEY_ANIM_TYPE, mAnimationType);
382                b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
383                b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
384                break;
385            case ANIM_SCALE_UP:
386                b.putInt(KEY_ANIM_TYPE, mAnimationType);
387                b.putInt(KEY_ANIM_START_X, mStartX);
388                b.putInt(KEY_ANIM_START_Y, mStartY);
389                b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
390                b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
391                break;
392            case ANIM_THUMBNAIL:
393                b.putInt(KEY_ANIM_TYPE, mAnimationType);
394                b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
395                b.putInt(KEY_ANIM_START_X, mStartX);
396                b.putInt(KEY_ANIM_START_Y, mStartY);
397                b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
398                        != null ? mAnimationStartedListener.asBinder() : null);
399                break;
400        }
401        return b;
402    }
403}
404