19306f07b1d66f4974a81f781d29739b30124fff0George Mount/*
29306f07b1d66f4974a81f781d29739b30124fff0George Mount * Copyright (C) 2014 The Android Open Source Project
39306f07b1d66f4974a81f781d29739b30124fff0George Mount *
49306f07b1d66f4974a81f781d29739b30124fff0George Mount * Licensed under the Apache License, Version 2.0 (the "License");
59306f07b1d66f4974a81f781d29739b30124fff0George Mount * you may not use this file except in compliance with the License.
69306f07b1d66f4974a81f781d29739b30124fff0George Mount * You may obtain a copy of the License at
79306f07b1d66f4974a81f781d29739b30124fff0George Mount *
89306f07b1d66f4974a81f781d29739b30124fff0George Mount *      http://www.apache.org/licenses/LICENSE-2.0
99306f07b1d66f4974a81f781d29739b30124fff0George Mount *
109306f07b1d66f4974a81f781d29739b30124fff0George Mount * Unless required by applicable law or agreed to in writing, software
119306f07b1d66f4974a81f781d29739b30124fff0George Mount * distributed under the License is distributed on an "AS IS" BASIS,
129306f07b1d66f4974a81f781d29739b30124fff0George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139306f07b1d66f4974a81f781d29739b30124fff0George Mount * See the License for the specific language governing permissions and
149306f07b1d66f4974a81f781d29739b30124fff0George Mount * limitations under the License.
159306f07b1d66f4974a81f781d29739b30124fff0George Mount */
169306f07b1d66f4974a81f781d29739b30124fff0George Mountpackage android.support.v4.app;
179306f07b1d66f4974a81f781d29739b30124fff0George Mount
189306f07b1d66f4974a81f781d29739b30124fff0George Mountimport android.content.Context;
199306f07b1d66f4974a81f781d29739b30124fff0George Mountimport android.graphics.Bitmap;
209306f07b1d66f4974a81f781d29739b30124fff0George Mountimport android.graphics.Canvas;
219306f07b1d66f4974a81f781d29739b30124fff0George Mountimport android.graphics.Matrix;
22b81a2943b9e150c6caca969e62c5375928c4cd1cDake Guimport android.graphics.Rect;
239306f07b1d66f4974a81f781d29739b30124fff0George Mountimport android.graphics.RectF;
249306f07b1d66f4974a81f781d29739b30124fff0George Mountimport android.graphics.drawable.BitmapDrawable;
25b81a2943b9e150c6caca969e62c5375928c4cd1cDake Guimport android.graphics.drawable.Drawable;
26b81a2943b9e150c6caca969e62c5375928c4cd1cDake Guimport android.os.Bundle;
279306f07b1d66f4974a81f781d29739b30124fff0George Mountimport android.os.Parcelable;
289306f07b1d66f4974a81f781d29739b30124fff0George Mountimport android.view.View;
299306f07b1d66f4974a81f781d29739b30124fff0George Mountimport android.widget.ImageView;
30b81a2943b9e150c6caca969e62c5375928c4cd1cDake Guimport android.widget.ImageView.ScaleType;
319306f07b1d66f4974a81f781d29739b30124fff0George Mount
329306f07b1d66f4974a81f781d29739b30124fff0George Mountimport java.util.List;
339306f07b1d66f4974a81f781d29739b30124fff0George Mountimport java.util.Map;
349306f07b1d66f4974a81f781d29739b30124fff0George Mount
359306f07b1d66f4974a81f781d29739b30124fff0George Mount/**
369306f07b1d66f4974a81f781d29739b30124fff0George Mount * Listener provided in
379306f07b1d66f4974a81f781d29739b30124fff0George Mount * {@link FragmentActivity#setEnterSharedElementCallback(SharedElementCallback)} and
389306f07b1d66f4974a81f781d29739b30124fff0George Mount * {@link FragmentActivity#setExitSharedElementCallback(SharedElementCallback)}
399306f07b1d66f4974a81f781d29739b30124fff0George Mount * to monitor the Activity transitions. The events can be used to customize Activity
409306f07b1d66f4974a81f781d29739b30124fff0George Mount * Transition behavior.
419306f07b1d66f4974a81f781d29739b30124fff0George Mount */
429306f07b1d66f4974a81f781d29739b30124fff0George Mountpublic abstract class SharedElementCallback {
439306f07b1d66f4974a81f781d29739b30124fff0George Mount    private Matrix mTempMatrix;
44b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private static int MAX_IMAGE_SIZE = (1024 * 1024);
45b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private static final String BUNDLE_SNAPSHOT_BITMAP = "sharedElement:snapshot:bitmap";
46b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private static final String BUNDLE_SNAPSHOT_IMAGE_SCALETYPE = "sharedElement:snapshot:imageScaleType";
47b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private static final String BUNDLE_SNAPSHOT_IMAGE_MATRIX = "sharedElement:snapshot:imageMatrix";
489306f07b1d66f4974a81f781d29739b30124fff0George Mount
499306f07b1d66f4974a81f781d29739b30124fff0George Mount    /**
500094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * In Activity Transitions, onSharedElementStart is called immediately before
510094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * capturing the start of the shared element state on enter and reenter transitions and
520094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * immediately before capturing the end of the shared element state for exit and return
530094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * transitions.
540094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * <p>
550094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * In Fragment Transitions, onSharedElementStart is called immediately before capturing the
560094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * start state of all shared element transitions.
570094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * <p>
580094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * This call can be used to adjust the transition start state by modifying the shared
590094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * element Views. Note that no layout step will be executed between onSharedElementStart
600094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * and the transition state capture.
610094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * <p>
620094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * For Activity Transitions, any changes made in {@link #onSharedElementEnd(List, List, List)}
630094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * that are not updated during layout should be corrected in onSharedElementStart for exit and
640094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * return transitions. For example, rotation or scale will not be affected by layout and
650094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * if changed in {@link #onSharedElementEnd(List, List, List)}, it will also have to be reset
660094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * in onSharedElementStart again to correct the end state.
679306f07b1d66f4974a81f781d29739b30124fff0George Mount     *
689306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param sharedElementNames The names of the shared elements that were accepted into
699306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                           the View hierarchy.
709306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param sharedElements The shared elements that are part of the View hierarchy.
719306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param sharedElementSnapshots The Views containing snap shots of the shared element
729306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               from the launching Window. These elements will not
739306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               be part of the scene, but will be positioned relative
749306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               to the Window decor View. This list is null for Fragment
759306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               Transitions.
769306f07b1d66f4974a81f781d29739b30124fff0George Mount     */
779306f07b1d66f4974a81f781d29739b30124fff0George Mount    public void onSharedElementStart(List<String> sharedElementNames,
789306f07b1d66f4974a81f781d29739b30124fff0George Mount            List<View> sharedElements, List<View> sharedElementSnapshots) {}
799306f07b1d66f4974a81f781d29739b30124fff0George Mount
809306f07b1d66f4974a81f781d29739b30124fff0George Mount    /**
810094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * In Activity Transitions, onSharedElementEnd is called immediately before
820094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * capturing the end of the shared element state on enter and reenter transitions and
830094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * immediately before capturing the start of the shared element state for exit and return
840094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * transitions.
850094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * <p>
860094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * In Fragment Transitions, onSharedElementEnd is called immediately before capturing the
870094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * end state of all shared element transitions.
880094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * <p>
890094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * This call can be used to adjust the transition end state by modifying the shared
900094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * element Views. Note that no layout step will be executed between onSharedElementEnd
910094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * and the transition state capture.
929306f07b1d66f4974a81f781d29739b30124fff0George Mount     * <p>
930094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * Any changes made in {@link #onSharedElementStart(List, List, List)} that are not updated
940094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * during layout should be corrected in onSharedElementEnd. For example, rotation or scale
950094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * will not be affected by layout and if changed in
960094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * {@link #onSharedElementStart(List, List, List)}, it will also have to be reset in
970094e26ee39675042cf0545ecdf3b5b3a363efb8George Mount     * onSharedElementEnd again to correct the end state.
989306f07b1d66f4974a81f781d29739b30124fff0George Mount     *
999306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param sharedElementNames The names of the shared elements that were accepted into
1009306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                           the View hierarchy.
1019306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param sharedElements The shared elements that are part of the View hierarchy.
1029306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param sharedElementSnapshots The Views containing snap shots of the shared element
1039306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               from the launching Window. These elements will not
1049306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               be part of the scene, but will be positioned relative
1059306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               to the Window decor View. This list will be null for
1069306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               Fragment Transitions.
1079306f07b1d66f4974a81f781d29739b30124fff0George Mount     */
1089306f07b1d66f4974a81f781d29739b30124fff0George Mount    public void onSharedElementEnd(List<String> sharedElementNames,
1099306f07b1d66f4974a81f781d29739b30124fff0George Mount            List<View> sharedElements, List<View> sharedElementSnapshots) {}
1109306f07b1d66f4974a81f781d29739b30124fff0George Mount
1119306f07b1d66f4974a81f781d29739b30124fff0George Mount    /**
1129306f07b1d66f4974a81f781d29739b30124fff0George Mount     * Called after {@link #onMapSharedElements(java.util.List, java.util.Map)} when
1139306f07b1d66f4974a81f781d29739b30124fff0George Mount     * transferring shared elements in. Any shared elements that have no mapping will be in
1149306f07b1d66f4974a81f781d29739b30124fff0George Mount     * <var>rejectedSharedElements</var>. The elements remaining in
1159306f07b1d66f4974a81f781d29739b30124fff0George Mount     * <var>rejectedSharedElements</var> will be transitioned out of the Scene. If a
1169306f07b1d66f4974a81f781d29739b30124fff0George Mount     * View is removed from <var>rejectedSharedElements</var>, it must be handled by the
1179306f07b1d66f4974a81f781d29739b30124fff0George Mount     * <code>SharedElementListener</code>.
1189306f07b1d66f4974a81f781d29739b30124fff0George Mount     * <p>
1199306f07b1d66f4974a81f781d29739b30124fff0George Mount     * Views in rejectedSharedElements will have their position and size set to the
1209306f07b1d66f4974a81f781d29739b30124fff0George Mount     * position of the calling shared element, relative to the Window decor View and contain
1219306f07b1d66f4974a81f781d29739b30124fff0George Mount     * snapshots of the View from the calling Activity or Fragment. This
1229306f07b1d66f4974a81f781d29739b30124fff0George Mount     * view may be safely added to the decor View's overlay to remain in position.
1239306f07b1d66f4974a81f781d29739b30124fff0George Mount     * </p>
1249306f07b1d66f4974a81f781d29739b30124fff0George Mount     * <p>This method is not called for Fragment Transitions. All rejected shared elements
1259306f07b1d66f4974a81f781d29739b30124fff0George Mount     * will be handled by the exit transition.</p>
1269306f07b1d66f4974a81f781d29739b30124fff0George Mount     *
1279306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param rejectedSharedElements Views containing visual information of shared elements
1289306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               that are not part of the entering scene. These Views
1299306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               are positioned relative to the Window decor View. A
1309306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               View removed from this list will not be transitioned
1319306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                               automatically.
1329306f07b1d66f4974a81f781d29739b30124fff0George Mount     */
1339306f07b1d66f4974a81f781d29739b30124fff0George Mount    public void onRejectSharedElements(List<View> rejectedSharedElements) {}
1349306f07b1d66f4974a81f781d29739b30124fff0George Mount
1359306f07b1d66f4974a81f781d29739b30124fff0George Mount    /**
1369306f07b1d66f4974a81f781d29739b30124fff0George Mount     * Lets the SharedElementCallback adjust the mapping of shared element names to
1379306f07b1d66f4974a81f781d29739b30124fff0George Mount     * Views.
1389306f07b1d66f4974a81f781d29739b30124fff0George Mount     *
1399306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param names The names of all shared elements transferred from the calling Activity
1409306f07b1d66f4974a81f781d29739b30124fff0George Mount     *              or Fragment in the order they were provided.
1419306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param sharedElements The mapping of shared element names to Views. The best guess
1429306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                       will be filled into sharedElements based on the transitionNames.
1439306f07b1d66f4974a81f781d29739b30124fff0George Mount     */
1449306f07b1d66f4974a81f781d29739b30124fff0George Mount    public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {}
1459306f07b1d66f4974a81f781d29739b30124fff0George Mount
1469306f07b1d66f4974a81f781d29739b30124fff0George Mount
1479306f07b1d66f4974a81f781d29739b30124fff0George Mount    /**
1489306f07b1d66f4974a81f781d29739b30124fff0George Mount     * Creates a snapshot of a shared element to be used by the remote Activity and reconstituted
1499306f07b1d66f4974a81f781d29739b30124fff0George Mount     * with {@link #onCreateSnapshotView(android.content.Context, android.os.Parcelable)}. A
1509306f07b1d66f4974a81f781d29739b30124fff0George Mount     * null return value will mean that the remote Activity will have a null snapshot View in
1519306f07b1d66f4974a81f781d29739b30124fff0George Mount     * {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)} and
1529306f07b1d66f4974a81f781d29739b30124fff0George Mount     * {@link #onSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
1539306f07b1d66f4974a81f781d29739b30124fff0George Mount     *
1549306f07b1d66f4974a81f781d29739b30124fff0George Mount     * <p>This is not called for Fragment Transitions.</p>
1559306f07b1d66f4974a81f781d29739b30124fff0George Mount     *
1569306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param sharedElement The shared element View to create a snapshot for.
1579306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param viewToGlobalMatrix A matrix containing a transform from the view to the screen
1589306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                           coordinates.
1599306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param screenBounds The bounds of shared element in screen coordinate space. This is
1609306f07b1d66f4974a81f781d29739b30124fff0George Mount     *                     the bounds of the view with the viewToGlobalMatrix applied.
1619306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @return A snapshot to send to the remote Activity to be reconstituted with
1629306f07b1d66f4974a81f781d29739b30124fff0George Mount     * {@link #onCreateSnapshotView(android.content.Context, android.os.Parcelable)} and passed
1639306f07b1d66f4974a81f781d29739b30124fff0George Mount     * into {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)} and
1649306f07b1d66f4974a81f781d29739b30124fff0George Mount     * {@link #onSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
1659306f07b1d66f4974a81f781d29739b30124fff0George Mount     */
1669306f07b1d66f4974a81f781d29739b30124fff0George Mount    public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,
1679306f07b1d66f4974a81f781d29739b30124fff0George Mount            RectF screenBounds) {
168b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        if (sharedElement instanceof ImageView) {
169b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            ImageView imageView = ((ImageView) sharedElement);
170b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            Drawable d = imageView.getDrawable();
171b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            Drawable bg = imageView.getBackground();
172b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            if (d != null && bg == null) {
173b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                Bitmap bitmap = createDrawableBitmap(d);
174b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                if (bitmap != null) {
175b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                    Bundle bundle = new Bundle();
176b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                    bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap);
177b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                    bundle.putString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE,
178b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                            imageView.getScaleType().toString());
179b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                    if (imageView.getScaleType() == ScaleType.MATRIX) {
180b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                        Matrix matrix = imageView.getImageMatrix();
181b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                        float[] values = new float[9];
182b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                        matrix.getValues(values);
183b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                        bundle.putFloatArray(BUNDLE_SNAPSHOT_IMAGE_MATRIX, values);
184b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                    }
185b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                    return bundle;
186b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                }
187b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            }
188b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        }
1899306f07b1d66f4974a81f781d29739b30124fff0George Mount        int bitmapWidth = Math.round(screenBounds.width());
1909306f07b1d66f4974a81f781d29739b30124fff0George Mount        int bitmapHeight = Math.round(screenBounds.height());
1919306f07b1d66f4974a81f781d29739b30124fff0George Mount        Bitmap bitmap = null;
1929306f07b1d66f4974a81f781d29739b30124fff0George Mount        if (bitmapWidth > 0 && bitmapHeight > 0) {
193fa79d6fc148a0642f240377b8ce82acfee7bb890Aurimas Liutikas            float scale = Math.min(1f, ((float) MAX_IMAGE_SIZE) / (bitmapWidth * bitmapHeight));
194fa79d6fc148a0642f240377b8ce82acfee7bb890Aurimas Liutikas            bitmapWidth = (int) (bitmapWidth * scale);
195fa79d6fc148a0642f240377b8ce82acfee7bb890Aurimas Liutikas            bitmapHeight = (int) (bitmapHeight * scale);
1969306f07b1d66f4974a81f781d29739b30124fff0George Mount            if (mTempMatrix == null) {
1979306f07b1d66f4974a81f781d29739b30124fff0George Mount                mTempMatrix = new Matrix();
1989306f07b1d66f4974a81f781d29739b30124fff0George Mount            }
1999306f07b1d66f4974a81f781d29739b30124fff0George Mount            mTempMatrix.set(viewToGlobalMatrix);
2009306f07b1d66f4974a81f781d29739b30124fff0George Mount            mTempMatrix.postTranslate(-screenBounds.left, -screenBounds.top);
201b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            mTempMatrix.postScale(scale, scale);
2029306f07b1d66f4974a81f781d29739b30124fff0George Mount            bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
2039306f07b1d66f4974a81f781d29739b30124fff0George Mount            Canvas canvas = new Canvas(bitmap);
2049306f07b1d66f4974a81f781d29739b30124fff0George Mount            canvas.concat(mTempMatrix);
2059306f07b1d66f4974a81f781d29739b30124fff0George Mount            sharedElement.draw(canvas);
2069306f07b1d66f4974a81f781d29739b30124fff0George Mount        }
2079306f07b1d66f4974a81f781d29739b30124fff0George Mount        return bitmap;
2089306f07b1d66f4974a81f781d29739b30124fff0George Mount    }
2099306f07b1d66f4974a81f781d29739b30124fff0George Mount
2109306f07b1d66f4974a81f781d29739b30124fff0George Mount    /**
211b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu     * Get a copy of bitmap of given drawable.
212b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu     */
213b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    private static Bitmap createDrawableBitmap(Drawable drawable) {
214b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        int width = drawable.getIntrinsicWidth();
215b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        int height = drawable.getIntrinsicHeight();
216b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        if (width <= 0 || height <= 0) {
217b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            return null;
218b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        }
219b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        float scale = Math.min(1f, ((float)MAX_IMAGE_SIZE) / (width * height));
220b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        if (drawable instanceof BitmapDrawable && scale == 1f) {
221b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            // return same bitmap if scale down not needed
222b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            return ((BitmapDrawable) drawable).getBitmap();
223b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        }
224b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        int bitmapWidth = (int) (width * scale);
225b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        int bitmapHeight = (int) (height * scale);
226b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
227b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        Canvas canvas = new Canvas(bitmap);
228b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        Rect existingBounds = drawable.getBounds();
229b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        int left = existingBounds.left;
230b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        int top = existingBounds.top;
231b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        int right = existingBounds.right;
232b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        int bottom = existingBounds.bottom;
233b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        drawable.setBounds(0, 0, bitmapWidth, bitmapHeight);
234b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        drawable.draw(canvas);
235b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        drawable.setBounds(left, top, right, bottom);
236b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        return bitmap;
237b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    }
238b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu
239b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu    /**
2409306f07b1d66f4974a81f781d29739b30124fff0George Mount     * Reconstitutes a snapshot View from a Parcelable returned in
2419306f07b1d66f4974a81f781d29739b30124fff0George Mount     * {@link #onCaptureSharedElementSnapshot(android.view.View, android.graphics.Matrix,
2429306f07b1d66f4974a81f781d29739b30124fff0George Mount     * android.graphics.RectF)} to be used in {@link #onSharedElementStart(java.util.List,
2439306f07b1d66f4974a81f781d29739b30124fff0George Mount     * java.util.List, java.util.List)} and {@link #onSharedElementEnd(java.util.List,
2449306f07b1d66f4974a81f781d29739b30124fff0George Mount     * java.util.List, java.util.List)}. The returned View will be sized and positioned after
2459306f07b1d66f4974a81f781d29739b30124fff0George Mount     * this call so that it is ready to be added to the decor View's overlay.
2469306f07b1d66f4974a81f781d29739b30124fff0George Mount     *
2479306f07b1d66f4974a81f781d29739b30124fff0George Mount     * <p>This is not called for Fragment Transitions.</p>
2489306f07b1d66f4974a81f781d29739b30124fff0George Mount     *
2499306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param context The Context used to create the snapshot View.
2509306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @param snapshot The Parcelable returned by {@link #onCaptureSharedElementSnapshot(
2519306f07b1d66f4974a81f781d29739b30124fff0George Mount     * android.view.View, android.graphics.Matrix, android.graphics.RectF)}.
2529306f07b1d66f4974a81f781d29739b30124fff0George Mount     * @return A View to be sent in {@link #onSharedElementStart(java.util.List, java.util.List,
2539306f07b1d66f4974a81f781d29739b30124fff0George Mount     * java.util.List)} and {@link #onSharedElementEnd(java.util.List, java.util.List,
2549306f07b1d66f4974a81f781d29739b30124fff0George Mount     * java.util.List)}. A null value will produce a null snapshot value for those two methods.
2559306f07b1d66f4974a81f781d29739b30124fff0George Mount     */
2569306f07b1d66f4974a81f781d29739b30124fff0George Mount    public View onCreateSnapshotView(Context context, Parcelable snapshot) {
2579306f07b1d66f4974a81f781d29739b30124fff0George Mount        ImageView view = null;
258b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        if (snapshot instanceof Bundle) {
259b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            Bundle bundle = (Bundle) snapshot;
260b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            Bitmap bitmap = (Bitmap) bundle.getParcelable(BUNDLE_SNAPSHOT_BITMAP);
261b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            if (bitmap == null) {
262b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                return null;
263b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            }
264b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            ImageView imageView = new ImageView(context);
265b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            view = imageView;
266b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            imageView.setImageBitmap(bitmap);
267b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            imageView.setScaleType(
268b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                    ScaleType.valueOf(bundle.getString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE)));
269b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            if (imageView.getScaleType() == ScaleType.MATRIX) {
270b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                float[] values = bundle.getFloatArray(BUNDLE_SNAPSHOT_IMAGE_MATRIX);
271b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                Matrix matrix = new Matrix();
272b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                matrix.setValues(values);
273b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu                imageView.setImageMatrix(matrix);
274b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu            }
275b81a2943b9e150c6caca969e62c5375928c4cd1cDake Gu        } else if (snapshot instanceof Bitmap) {
2769306f07b1d66f4974a81f781d29739b30124fff0George Mount            Bitmap bitmap = (Bitmap) snapshot;
2779306f07b1d66f4974a81f781d29739b30124fff0George Mount            view = new ImageView(context);
2789306f07b1d66f4974a81f781d29739b30124fff0George Mount            view.setImageBitmap(bitmap);
2799306f07b1d66f4974a81f781d29739b30124fff0George Mount        }
2809306f07b1d66f4974a81f781d29739b30124fff0George Mount        return view;
2819306f07b1d66f4974a81f781d29739b30124fff0George Mount    }
2829306f07b1d66f4974a81f781d29739b30124fff0George Mount
2830d5b0e011d7db522a576450593cf38170b997501Abhinav Baid    /**
2840d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * Called during an Activity Transition when the shared elements have arrived at the
2850d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * final location and are ready to be transferred. This method is called for both the
2860d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * source and destination Activities.
2870d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * <p>
2880d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * When the shared elements are ready to be transferred,
2890d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * {@link OnSharedElementsReadyListener#onSharedElementsReady()}
2900d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * must be called to trigger the transfer.
2910d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * <p>
2920d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * The default behavior is to trigger the transfer immediately.
2930d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     *
2940d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * @param sharedElementNames The names of the shared elements that are being transferred..
2950d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * @param sharedElements The shared elements that are part of the View hierarchy.
2960d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * @param listener The listener to call when the shared elements are ready to be hidden
2970d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     *                 in the source Activity or shown in the destination Activity.
2980d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     */
2990d5b0e011d7db522a576450593cf38170b997501Abhinav Baid    public void onSharedElementsArrived(List<String> sharedElementNames,
3000d5b0e011d7db522a576450593cf38170b997501Abhinav Baid            List<View> sharedElements, OnSharedElementsReadyListener listener) {
3010d5b0e011d7db522a576450593cf38170b997501Abhinav Baid        listener.onSharedElementsReady();
3020d5b0e011d7db522a576450593cf38170b997501Abhinav Baid    }
3030d5b0e011d7db522a576450593cf38170b997501Abhinav Baid
3040d5b0e011d7db522a576450593cf38170b997501Abhinav Baid    /**
3050d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * Listener to be called after {@link
3060d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * SharedElementCallback#onSharedElementsArrived(List, List, OnSharedElementsReadyListener)}
3070d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * when the shared elements are ready to be hidden in the source Activity and shown in the
3080d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     * destination Activity.
3090d5b0e011d7db522a576450593cf38170b997501Abhinav Baid     */
3100d5b0e011d7db522a576450593cf38170b997501Abhinav Baid    public interface OnSharedElementsReadyListener {
3110d5b0e011d7db522a576450593cf38170b997501Abhinav Baid
3120d5b0e011d7db522a576450593cf38170b997501Abhinav Baid        /**
3130d5b0e011d7db522a576450593cf38170b997501Abhinav Baid         * Call this method during or after the OnSharedElementsReadyListener has been received
3140d5b0e011d7db522a576450593cf38170b997501Abhinav Baid         * in {@link SharedElementCallback#onSharedElementsArrived(List, List,
3150d5b0e011d7db522a576450593cf38170b997501Abhinav Baid         * OnSharedElementsReadyListener)} to indicate that the shared elements are ready to be
3160d5b0e011d7db522a576450593cf38170b997501Abhinav Baid         * hidden in the source and shown in the destination Activity.
3170d5b0e011d7db522a576450593cf38170b997501Abhinav Baid         */
3180d5b0e011d7db522a576450593cf38170b997501Abhinav Baid        void onSharedElementsReady();
3190d5b0e011d7db522a576450593cf38170b997501Abhinav Baid    }
3209306f07b1d66f4974a81f781d29739b30124fff0George Mount}
321