SendUi.java revision 5438ab0e17064e20870ac893a2dd2b9e1219eef1
15438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly/*
25438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * Copyright (C) 2011 The Android Open Source Project
35438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly *
45438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
55438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * you may not use this file except in compliance with the License.
65438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * You may obtain a copy of the License at
75438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly *
85438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
95438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly *
105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * Unless required by applicable law or agreed to in writing, software
115438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
125438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * See the License for the specific language governing permissions and
145438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * limitations under the License.
155438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */
165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
175438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellypackage com.android.nfc;
185438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport com.android.nfc3.R;
205438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
215438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.Animator;
225438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.ObjectAnimator;
235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.animation.PropertyValuesHolder;
245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.content.Context;
255438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Bitmap;
265438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Canvas;
275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.Matrix;
285438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.graphics.PixelFormat;
295438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.os.Binder;
305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.util.DisplayMetrics;
315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.Display;
325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.LayoutInflater;
335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.Surface;
345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.View;
355438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.ViewGroup;
365438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.view.WindowManager;
375438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellyimport android.widget.ImageView;
385438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
395438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly/**
405438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly * All methods must be called on UI thread
415438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly */
425438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pellypublic class SendUi implements Animator.AnimatorListener {
435438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
445438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    static final float[] PRE_SCREENSHOT_SCALE = {1.0f, 0.6f};
455438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    static final int PRE_DURATION_MS = 50;
465438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
475438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    static final float[] POST_SCREENSHOT_SCALE = {0.6f, 0.0f};
485438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    static final int POST_DURATION_MS = 200;
495438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
505438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    // all members are only used on UI thread
515438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final WindowManager mWindowManager;
525438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final Context mContext;
535438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final Display mDisplay;
545438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final DisplayMetrics mDisplayMetrics;
555438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final Matrix mDisplayMatrix;
565438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final WindowManager.LayoutParams mWindowLayoutParams;
575438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final LayoutInflater mLayoutInflater;
585438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final View mScreenshotLayout;
595438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final ImageView mScreenshotView;
605438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final Callback mCallback;
615438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final ObjectAnimator mPreAnimator;
625438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    final ObjectAnimator mPostAnimator;
635438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
645438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    Bitmap mScreenshotBitmap;
655438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    boolean mAttached;
665438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
675438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    interface Callback {
685438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        public void onPreFinished();
695438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    }
705438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
715438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    public SendUi(Context context, Callback callback) {
725438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mContext = context;
735438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mCallback = callback;
745438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
755438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mDisplayMetrics = new DisplayMetrics();
765438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mDisplayMatrix = new Matrix();
775438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
785438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mDisplay = mWindowManager.getDefaultDisplay();
795438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
805438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mLayoutInflater = (LayoutInflater)
815438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
825438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mScreenshotLayout = mLayoutInflater.inflate(R.layout.screenshot, null);
835438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.screenshot);
845438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mScreenshotLayout.setFocusable(true);
855438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
865438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mWindowLayoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
875438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly                ViewGroup.LayoutParams.MATCH_PARENT, 0, 0, 0,
885438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly                WindowManager.LayoutParams.FLAG_FULLSCREEN
895438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
905438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED_SYSTEM
915438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly                | WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING
925438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
935438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly                | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
945438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly                PixelFormat.OPAQUE);
955438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mWindowLayoutParams.token = new Binder();
965438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
975438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        PropertyValuesHolder preX = PropertyValuesHolder.ofFloat("scaleX", PRE_SCREENSHOT_SCALE);
985438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        PropertyValuesHolder preY = PropertyValuesHolder.ofFloat("scaleY", PRE_SCREENSHOT_SCALE);
995438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPreAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, preX, preY);
1005438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPreAnimator.setInterpolator(null);  // linear
1015438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPreAnimator.setDuration(PRE_DURATION_MS);
1025438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPreAnimator.addListener(this);
1035438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1045438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        PropertyValuesHolder postX = PropertyValuesHolder.ofFloat("scaleX", POST_SCREENSHOT_SCALE);
1055438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", POST_SCREENSHOT_SCALE);
1065438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPostAnimator = ObjectAnimator.ofPropertyValuesHolder(mScreenshotView, postX, postY);
1075438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPostAnimator.setInterpolator(null);  // linear
1085438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPostAnimator.setDuration(POST_DURATION_MS);
1095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPostAnimator.addListener(this);
1105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1115438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mAttached = false;
1125438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    }
1135438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1145438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    public void takeScreenshot() {
1155438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mScreenshotBitmap = createScreenshot();
1165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    }
1175438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1185438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    /** Show pre-send animation, calls onPreFinished() when complete */
1195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    public void showPreSend() {
1205438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        if (mScreenshotBitmap == null || mAttached) {
1215438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            return;
1225438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        }
1235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mScreenshotView.setImageBitmap(mScreenshotBitmap);
1245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mScreenshotLayout.requestFocus();
1255438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
1265438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mAttached = true;
1275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPreAnimator.start();
1285438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1295438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        //TODO: Lock rotation
1305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly//        final int orientation = getResources().getConfiguration().orientation;
1315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly//        setRequestedOrientation(orientation);
1325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    }
1335438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1345438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    /** Show post-send animation */
1355438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    public void showPostSend() {
1365438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        if (!mAttached) {
1375438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            return;
1385438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        }
1395438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPostAnimator.start();
1405438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    }
1415438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1425438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    public void dismiss() {
1435438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        if (!mAttached) {
1445438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            return;
1455438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        }
1465438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPreAnimator.cancel();
1475438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mPostAnimator.cancel();
1485438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mWindowManager.removeView(mScreenshotLayout);
1495438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mAttached = false;
1505438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        releaseScreenshot();
1515438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    }
1525438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1535438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    public void releaseScreenshot() {
1545438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mScreenshotBitmap = null;
1555438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    }
1565438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1575438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    /**
1585438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly     * @return the current display rotation in degrees
1595438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly     */
1605438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    static float getDegreesForRotation(int value) {
1615438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        switch (value) {
1625438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        case Surface.ROTATION_90:
1635438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            return 90f;
1645438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        case Surface.ROTATION_180:
1655438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            return 180f;
1665438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        case Surface.ROTATION_270:
1675438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            return 270f;
1685438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        }
1695438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        return 0f;
1705438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    }
1715438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1725438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    /**
1735438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly     * Returns a screenshot of the current display contents.
1745438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly     * @param context Context.
1755438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly     * @return
1765438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly     */
1775438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    Bitmap createScreenshot() {
1785438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        // We need to orient the screenshot correctly (and the Surface api seems to
1795438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        // take screenshots only in the natural orientation of the device :!)
1805438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        mDisplay.getRealMetrics(mDisplayMetrics);
1815438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};
1825438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        float degrees = getDegreesForRotation(mDisplay.getRotation());
1835438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        boolean requiresRotation = (degrees > 0);
1845438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        if (requiresRotation) {
1855438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            // Get the dimensions of the device in its native orientation
1865438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            mDisplayMatrix.reset();
1875438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            mDisplayMatrix.preRotate(-degrees);
1885438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            mDisplayMatrix.mapPoints(dims);
1895438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            dims[0] = Math.abs(dims[0]);
1905438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            dims[1] = Math.abs(dims[1]);
1915438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        }
1925438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1935438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        Bitmap bitmap = Surface.screenshot((int) dims[0], (int) dims[1]);
1945438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        // Bail if we couldn't take the screenshot
1955438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        if (bitmap == null) {
1965438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            return null;
1975438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        }
1985438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
1995438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        if (requiresRotation) {
2005438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            // Rotate the screenshot to the current orientation
2015438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels,
2025438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly                    mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
2035438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            Canvas c = new Canvas(ss);
2045438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
2055438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            c.rotate(360f - degrees);
2065438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            c.translate(-dims[0] / 2, -dims[1] / 2);
2075438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            c.drawBitmap(bitmap, 0, 0, null);
2085438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
2095438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            bitmap = ss;
2105438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        }
2115438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
2125438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        return bitmap;
2135438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    }
2145438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
2155438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    @Override
2165438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    public void onAnimationStart(Animator animation) {  }
2175438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
2185438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    @Override
2195438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    public void onAnimationEnd(Animator animation) {
2205438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        if (animation == mPreAnimator) {
2215438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            mCallback.onPreFinished();
2225438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        } else if (animation == mPostAnimator) {
2235438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly            dismiss();
2245438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly        }
2255438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    }
2265438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
2275438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    @Override
2285438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    public void onAnimationCancel(Animator animation) {  }
2295438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly
2305438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    @Override
2315438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly    public void onAnimationRepeat(Animator animation) {  }
2325438ab0e17064e20870ac893a2dd2b9e1219eef1Nick Pelly}
233