DragView.java revision 4a5fd100d743fcd9e51c2da36a9f9f542c5b5cdd
100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato/*
200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Copyright (C) 2008 The Android Open Source Project
300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato *
400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * you may not use this file except in compliance with the License.
600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * You may obtain a copy of the License at
700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato *
800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato *      http://www.apache.org/licenses/LICENSE-2.0
900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato *
1000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Unless required by applicable law or agreed to in writing, software
1100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
1200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * See the License for the specific language governing permissions and
1400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * limitations under the License.
1500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato */
1600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
17fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevpackage com.android.launcher3.dragndrop;
1800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
19d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshevimport android.animation.Animator;
20d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshevimport android.animation.AnimatorListenerAdapter;
21fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyalimport android.animation.FloatArrayEvaluator;
22a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroyimport android.animation.ValueAnimator;
23a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroyimport android.animation.ValueAnimator.AnimatorUpdateListener;
2442e28092b336bf89bee94c61e2cd327e1d8ec882Sunny Goyalimport android.annotation.SuppressLint;
254a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.content.pm.PackageManager;
2600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Bitmap;
2700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Canvas;
28fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyalimport android.graphics.ColorMatrix;
29fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyalimport android.graphics.ColorMatrixColorFilter;
304a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.graphics.Matrix;
3100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Paint;
324a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.graphics.Path;
33b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chungimport android.graphics.Point;
34e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohenimport android.graphics.Rect;
354a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.graphics.drawable.AdaptiveIconDrawable;
364a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.graphics.drawable.Drawable;
374a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.os.Handler;
384a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.os.Looper;
394a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.support.animation.DynamicAnimation;
404a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.support.animation.SpringAnimation;
414a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.support.animation.SpringForce;
4200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.View;
43a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroyimport android.view.animation.DecelerateInterpolator;
444a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.widget.FrameLayout;
454a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.widget.ImageView;
46fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshev
474a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport com.android.launcher3.ItemInfo;
48fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.Launcher;
49fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.LauncherAnimUtils;
504a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport com.android.launcher3.LauncherModel;
514a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport com.android.launcher3.LauncherSettings;
52ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickhamimport com.android.launcher3.R;
534a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport com.android.launcher3.Utilities;
544a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport com.android.launcher3.config.FeatureFlags;
556c82867a7ea3a95a19d6cec7d1fe164d234d2cb6Tony Wickhamimport com.android.launcher3.util.Themes;
56091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
57fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshev
58fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyalimport java.util.Arrays;
59fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
604a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
614a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
624a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songpublic class DragView extends FrameLayout {
63a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    public static final int COLOR_CHANGE_DURATION = 120;
64a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    public static final int VIEW_ZOOM_DURATION = 150;
65fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
66091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk static float sDragAlpha = 1f;
677bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
6800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private Bitmap mBitmap;
69ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    private Bitmap mCrossFadeBitmap;
70316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk Paint mPaint;
71c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda    private final int mBlurSizeOutline;
72d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    private final int mRegistrationX;
73d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    private final int mRegistrationY;
74ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham    private final float mInitialScale;
75ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham    private final int[] mTempLoc = new int[2];
7600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
77b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung    private Point mDragVisualizeOffset = null;
78e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    private Rect mDragRegion = null;
794a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private final Launcher mLauncher;
80d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    private final DragLayer mDragLayer;
8142e28092b336bf89bee94c61e2cd327e1d8ec882Sunny Goyal    @Thunk final DragController mDragController;
82fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen    private boolean mHasDrawn = false;
83091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk float mCrossFadeProgress = 0f;
84456e87e1943ee4e779929f77a9cf11de7af3ec6aVadim Tryshev    private boolean mAnimationCancelled = false;
85a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
86a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy    ValueAnimator mAnim;
87eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    // The intrinsic icon scale factor is the scale factor for a drag icon over the workspace
88eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    // size.  This is ignored for non-icons.
89eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    private float mIntrinsicIconScale = 1f;
9000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
91316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk float[] mCurrentFilter;
92fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal    private ValueAnimator mFilterAnimator;
93fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
94a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    private int mLastTouchX;
95a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    private int mLastTouchY;
96a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    private int mAnimatedShiftX;
97a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    private int mAnimatedShiftY;
98a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal
994a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    // Below variable only needed IF FeatureFlags.LAUNCHER3_SPRING_ICONS is {@code true}
1004a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private SpringAnimation mSpringX, mSpringY;
1014a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private ImageView mFgImageView, mBgImageView;
1024a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private Path mScaledMaskPath;
1034a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    // TODO: figure out if there is smarter way to retrieve these two constants below
1044a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private final static float ADAPTIVE_ICON_SCALE = .731121626f;
1054a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private final static float ADAPTIVE_ICON_MASK_SCALE = 1.165f; //1.185f;
1064a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
1074a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    // Following three values are fine tuned with motion ux designer
1084a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private final static int STIFFNESS = 4000;
1094a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private final static float DAMPENING_RATIO = 1f;
1104a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private final static int PARALLAX_MAX_IN_DP = 8;
1114a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private final int mDelta;
1124a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
11300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
11400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Construct the drag view.
11500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * <p>
11600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * The registration point is the point inside our view that the touch events should
11700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * be centered upon.
1188dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param launcher The Launcher instance
11900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * @param bitmap The view that we're dragging around.  We scale it up when we draw it.
12000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * @param registrationX The x coordinate of the registration point.
12100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * @param registrationY The y coordinate of the registration point.
12200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
123157793dda450b69da388b859d1c1a7a1083c4ec9Sunny Goyal    public DragView(Launcher launcher, Bitmap bitmap, int registrationX, int registrationY,
124157793dda450b69da388b859d1c1a7a1083c4ec9Sunny Goyal                    final float initialScale, final float finalScaleDps) {
1258dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        super(launcher);
1264a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        mLauncher = launcher;
1278dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mDragLayer = launcher.getDragLayer();
128d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        mDragController = launcher.getDragController();
12900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
130157793dda450b69da388b859d1c1a7a1083c4ec9Sunny Goyal        final float scale = (bitmap.getWidth() + finalScaleDps) / bitmap.getWidth();
131a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy
132307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // Set the initial scale to avoid any jumps
133307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        setScaleX(initialScale);
134307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        setScaleY(initialScale);
135307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen
136a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        // Animate the view into the correct position
137cda3bfb2e1d89ad872558dd0a82ae79ca6fe41eaJon Miranda        mAnim = LauncherAnimUtils.ofFloat(0f, 1f);
138a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mAnim.setDuration(VIEW_ZOOM_DURATION);
139a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        mAnim.addUpdateListener(new AnimatorUpdateListener() {
140a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy            @Override
141a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy            public void onAnimationUpdate(ValueAnimator animation) {
142a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy                final float value = (Float) animation.getAnimatedValue();
143a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy
14472d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung                setScaleX(initialScale + (value * (scale - initialScale)));
14572d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung                setScaleY(initialScale + (value * (scale - initialScale)));
146867ca62c0e4b811d46734ff940d59c7a787525c8Winson Chung                if (sDragAlpha != 1f) {
147867ca62c0e4b811d46734ff940d59c7a787525c8Winson Chung                    setAlpha(sDragAlpha * value + (1f - value));
148867ca62c0e4b811d46734ff940d59c7a787525c8Winson Chung                }
149a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy
150a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy                if (getParent() == null) {
151a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy                    animation.cancel();
152a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy                }
153a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy            }
154a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        });
15500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
156d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        mAnim.addListener(new AnimatorListenerAdapter() {
157d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev            @Override
158d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev            public void onAnimationEnd(Animator animation) {
159456e87e1943ee4e779929f77a9cf11de7af3ec6aVadim Tryshev                if (!mAnimationCancelled) {
160456e87e1943ee4e779929f77a9cf11de7af3ec6aVadim Tryshev                    mDragController.onDragViewAnimationEnd();
161456e87e1943ee4e779929f77a9cf11de7af3ec6aVadim Tryshev                }
162d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev            }
163d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        });
164d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev
165157793dda450b69da388b859d1c1a7a1083c4ec9Sunny Goyal        mBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight());
166157793dda450b69da388b859d1c1a7a1083c4ec9Sunny Goyal        setDragRegion(new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()));
16700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
16800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // The point in our scaled bitmap that the touch events are located
169a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        mRegistrationX = registrationX;
170a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        mRegistrationY = registrationY;
17162bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy
172ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham        mInitialScale = initialScale;
173ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham
17462bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy        // Force a measure, because Workspace uses getMeasuredHeight() before the layout pass
17562bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy        int ms = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
17662bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy        measure(ms, ms);
1776cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka        mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
17875deaf3d8f369bd13ea59ec3740324a5cfeb3099Sunny Goyal
179c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda        mBlurSizeOutline = getResources().getDimensionPixelSize(R.dimen.blur_size_medium_outline);
180a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal        setElevation(getResources().getDimension(R.dimen.drag_elevation));
1814a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        setWillNotDraw(false);
1824a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        mDelta = (int)(getResources().getDisplayMetrics().density * PARALLAX_MAX_IN_DP);
1834a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    }
1844a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
1854a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    /**
1864a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song     * Initialize {@code #mIconDrawable} only if the icon type is app icon (not shortcut or folder).
1874a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song     */
1884a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    public void setItemInfo(final ItemInfo info) {
1894a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        if (!(FeatureFlags.LAUNCHER3_SPRING_ICONS && Utilities.isAtLeastO())) {
1904a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            return;
1914a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        }
1924a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        if (!(info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
1934a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)) {
1944a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            return;
1954a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        }
1964a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        // Load the adaptive icon on a background thread and add the view in ui thread.
1974a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        final Looper workerLooper = LauncherModel.getWorkerLooper();
1984a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        new Handler(workerLooper).postAtFrontOfQueue(new Runnable() {
1994a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            @Override
2004a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            public void run() {
2014a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                PackageManager pm = (mLauncher).getPackageManager();
2024a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                try {
2034a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                    Drawable dr = pm.getActivityIcon(info.getTargetComponent());
2044a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                    if (dr instanceof AdaptiveIconDrawable) {
2054a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        int w = mBitmap.getWidth();
2064a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        int h = mBitmap.getHeight();
2074a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
2084a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        adaptiveIcon.setBounds(0, 0, w, h);
2094a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        setupMaskPath(adaptiveIcon);
2104a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        mFgImageView = setupImageView(adaptiveIcon.getForeground());
2114a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        mBgImageView = setupImageView(adaptiveIcon.getBackground());
2124a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        mSpringX = setupSpringAnimation(-w/4, w/4, DynamicAnimation.TRANSLATION_X);
2134a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        mSpringY = setupSpringAnimation(-h/4, h/4, DynamicAnimation.TRANSLATION_Y);
2144a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
2154a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        new Handler(Looper.getMainLooper()).post(new Runnable() {
2164a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                            @Override
2174a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                            public void run() {
2184a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                                addView(mBgImageView);
2194a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                                addView(mFgImageView);
2204a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                                setWillNotDraw(true);
2214a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                            }
2224a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        });
2234a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                    }
2244a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                } catch (PackageManager.NameNotFoundException e) { }
2254a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            }});
2264a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    }
2274a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
2284a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private ImageView setupImageView(Drawable drawable) {
2294a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        FrameLayout.LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
2304a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        ImageView imageViewOut = new ImageView(getContext());
2314a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        imageViewOut.setLayoutParams(params);
2324a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        imageViewOut.setScaleType(ImageView.ScaleType.CENTER);
2334a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        imageViewOut.setScaleX(ADAPTIVE_ICON_SCALE);
2344a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        imageViewOut.setScaleY(ADAPTIVE_ICON_SCALE);
2354a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        imageViewOut.setImageDrawable(drawable);
2364a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        return imageViewOut;
2374a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    }
2384a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
2394a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private SpringAnimation setupSpringAnimation(int minValue, int maxValue,
2404a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            DynamicAnimation.ViewProperty property) {
2414a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        SpringAnimation s = new SpringAnimation(mFgImageView, property, 0);
2424a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        s.setMinValue(minValue).setMaxValue(maxValue);
2434a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        s.setSpring(new SpringForce(0)
2444a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        .setDampingRatio(DAMPENING_RATIO)
2454a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                        .setStiffness(STIFFNESS));
2464a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        return s;
2474a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    }
2484a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
2494a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private void setupMaskPath(AdaptiveIconDrawable dr) {
2504a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        Matrix m = new Matrix();
2514a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        m.setScale(ADAPTIVE_ICON_SCALE * ADAPTIVE_ICON_MASK_SCALE,
2524a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                ADAPTIVE_ICON_SCALE * ADAPTIVE_ICON_MASK_SCALE,
2534a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                dr.getBounds().centerX(),
2544a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song                dr.getBounds().centerY());
2554a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        mScaledMaskPath = new Path();
2564a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        dr.getIconMask().transform(m, mScaledMaskPath);
2574a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    }
2584a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
2594a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private void applySpring(int x, int y) {
2604a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        if (mSpringX == null || mSpringY == null) {
2614a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            return;
2624a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        }
2634a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        mSpringX.animateToFinalPosition(Utilities.boundToRange(x, -mDelta, mDelta));
2644a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        mSpringY.animateToFinalPosition(Utilities.boundToRange(y, -mDelta, mDelta));
2654a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    }
2664a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
2674a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    @Override
2684a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
2694a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        int w = right - left;
2704a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        int h = bottom - top;
2714a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        for (int i = 0; i < getChildCount(); i++) {
2724a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            getChildAt(i).layout(-w / 4, -h / 4, w + w / 4, h + h / 4);
2734a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        }
2744a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    }
2754a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
2764a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    @Override
2774a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
2784a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        int w = mBitmap.getWidth();
2794a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        int h = mBitmap.getHeight();
2804a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        setMeasuredDimension(w, h);
2814a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        for (int i = 0; i < getChildCount(); i++) {
2824a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            getChildAt(i).measure(w, h);
2834a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        }
2844a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    }
2854a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
2864a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    @Override
2874a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    protected void dispatchDraw(Canvas canvas) {
2884a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        if (mScaledMaskPath != null) {
2894a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
2904a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            canvas.clipPath(mScaledMaskPath);
2914a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        }
2924a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        super.dispatchDraw(canvas);
29362bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy    }
29462bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy
295eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    /** Sets the scale of the view over the normal workspace icon size. */
296eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    public void setIntrinsicIconScaleFactor(float scale) {
297eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung        mIntrinsicIconScale = scale;
298eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    }
299eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung
300eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    public float getIntrinsicIconScaleFactor() {
301eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung        return mIntrinsicIconScale;
302eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    }
303eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung
304a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    public int getDragRegionLeft() {
305e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        return mDragRegion.left;
306a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
307a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
308a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    public int getDragRegionTop() {
309e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        return mDragRegion.top;
310a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
311a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
312a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    public int getDragRegionWidth() {
313e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        return mDragRegion.width();
314a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
315a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
316a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    public int getDragRegionHeight() {
317e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        return mDragRegion.height();
318e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    }
319e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen
320b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung    public void setDragVisualizeOffset(Point p) {
321b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung        mDragVisualizeOffset = p;
322b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung    }
323b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung
324b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung    public Point getDragVisualizeOffset() {
325b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung        return mDragVisualizeOffset;
326b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung    }
327b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung
328e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    public void setDragRegion(Rect r) {
329e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        mDragRegion = r;
330e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    }
331e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen
332e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    public Rect getDragRegion() {
333e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        return mDragRegion;
334a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
335a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
336d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    // Draws drag shadow for system DND.
33742e28092b336bf89bee94c61e2cd327e1d8ec882Sunny Goyal    @SuppressLint("WrongCall")
338d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    public void drawDragShadow(Canvas canvas) {
339d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        final int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
340d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        canvas.scale(getScaleX(), getScaleY());
341d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        onDraw(canvas);
342d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        canvas.restoreToCount(saveCount);
343d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    }
344d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev
345d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    // Provides drag shadow metrics for system DND.
346d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    public void provideDragShadowMetrics(Point size, Point touch) {
347d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        size.set((int)(mBitmap.getWidth() * getScaleX()), (int)(mBitmap.getHeight() * getScaleY()));
348d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev
34937bd006b73b4399ba10bb46e7f57a56b2e133e86Vadim Tryshev        final float xGrowth = mBitmap.getWidth() * (getScaleX() - 1);
35037bd006b73b4399ba10bb46e7f57a56b2e133e86Vadim Tryshev        final float yGrowth = mBitmap.getHeight() * (getScaleY() - 1);
3519430ff23c8a1127341e73b285e901a5cb9f1b5f7Vadim Tryshev        touch.set(
3529430ff23c8a1127341e73b285e901a5cb9f1b5f7Vadim Tryshev                mRegistrationX + (int)Math.round(xGrowth / 2),
3539430ff23c8a1127341e73b285e901a5cb9f1b5f7Vadim Tryshev                mRegistrationY + (int)Math.round(yGrowth / 2));
354d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    }
355d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev
35600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    @Override
35700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    protected void onDraw(Canvas canvas) {
358fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        mHasDrawn = true;
359ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        boolean crossFade = mCrossFadeProgress > 0 && mCrossFadeBitmap != null;
360ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        if (crossFade) {
361ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            int alpha = crossFade ? (int) (255 * (1 - mCrossFadeProgress)) : 255;
362ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            mPaint.setAlpha(alpha);
363ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        }
36400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
365ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        if (crossFade) {
366ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            mPaint.setAlpha((int) (255 * mCrossFadeProgress));
367d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev            final int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
368ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            float sX = (mBitmap.getWidth() * 1.0f) / mCrossFadeBitmap.getWidth();
369ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            float sY = (mBitmap.getHeight() * 1.0f) / mCrossFadeBitmap.getHeight();
370ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            canvas.scale(sX, sY);
371ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            canvas.drawBitmap(mCrossFadeBitmap, 0.0f, 0.0f, mPaint);
372d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev            canvas.restoreToCount(saveCount);
373ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        }
374ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
375ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
376ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public void setCrossFadeBitmap(Bitmap crossFadeBitmap) {
377ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        mCrossFadeBitmap = crossFadeBitmap;
378ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
379ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
380ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public void crossFade(int duration) {
381cda3bfb2e1d89ad872558dd0a82ae79ca6fe41eaJon Miranda        ValueAnimator va = LauncherAnimUtils.ofFloat(0f, 1f);
382ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        va.setDuration(duration);
383ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        va.setInterpolator(new DecelerateInterpolator(1.5f));
384ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        va.addUpdateListener(new AnimatorUpdateListener() {
385ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            @Override
386ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
387ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                mCrossFadeProgress = animation.getAnimatedFraction();
3885d2fc32e6da66f877dfba4fe513fbabdcdae5f99Sunny Goyal                invalidate();
389ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            }
390ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        });
391ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        va.start();
39200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
39300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
39461967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung    public void setColor(int color) {
3956cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka        if (mPaint == null) {
3966cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka            mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
3976cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka        }
39861967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        if (color != 0) {
399fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            ColorMatrix m1 = new ColorMatrix();
400fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            m1.setSaturation(0);
401fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
402fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            ColorMatrix m2 = new ColorMatrix();
4036c82867a7ea3a95a19d6cec7d1fe164d234d2cb6Tony Wickham            Themes.setColorScaleOnMatrix(color, m2);
404fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            m1.postConcat(m2);
405fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
406a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            animateFilterTo(m1.getArray());
40761967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        } else {
408a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            if (mCurrentFilter == null) {
409fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal                mPaint.setColorFilter(null);
410fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal                invalidate();
411fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            } else {
412fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal                animateFilterTo(new ColorMatrix().getArray());
413fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            }
41461967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        }
415fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal    }
416fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
417fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal    private void animateFilterTo(float[] targetFilter) {
418fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        float[] oldFilter = mCurrentFilter == null ? new ColorMatrix().getArray() : mCurrentFilter;
419fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        mCurrentFilter = Arrays.copyOf(oldFilter, oldFilter.length);
420fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
421fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        if (mFilterAnimator != null) {
422fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            mFilterAnimator.cancel();
423fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        }
424fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        mFilterAnimator = ValueAnimator.ofObject(new FloatArrayEvaluator(mCurrentFilter),
425fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal                oldFilter, targetFilter);
426fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        mFilterAnimator.setDuration(COLOR_CHANGE_DURATION);
427fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        mFilterAnimator.addUpdateListener(new AnimatorUpdateListener() {
428fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
429fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            @Override
430fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            public void onAnimationUpdate(ValueAnimator animation) {
431fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal                mPaint.setColorFilter(new ColorMatrixColorFilter(mCurrentFilter));
432fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal                invalidate();
433fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            }
434fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        });
435fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        mFilterAnimator.start();
43600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
43700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
438fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen    public boolean hasDrawn() {
439fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        return mHasDrawn;
440fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen    }
441fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen
4423e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    @Override
4433e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    public void setAlpha(float alpha) {
4443e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        super.setAlpha(alpha);
4453e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mPaint.setAlpha((int) (255 * alpha));
4463e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        invalidate();
4473e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    }
4483e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
44900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
45000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Create a window containing this view and show it.
45100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *
4528dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param touchX the x coordinate the user touched in DragLayer coordinates
4538dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param touchY the y coordinate the user touched in DragLayer coordinates
45400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
4558dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    public void show(int touchX, int touchY) {
4568dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mDragLayer.addView(this);
457043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
458043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Start the pick-up animation
4598dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        DragLayer.LayoutParams lp = new DragLayer.LayoutParams(0, 0);
4608dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        lp.width = mBitmap.getWidth();
4618dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        lp.height = mBitmap.getHeight();
4628dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        lp.customPosition = true;
4638dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        setLayoutParams(lp);
464a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        move(touchX, touchY);
465ca99383daef92fed673de22126875cb485be494fMichael Jurka        // Post the animation to skip other expensive work happening on the first frame
466ca99383daef92fed673de22126875cb485be494fMichael Jurka        post(new Runnable() {
467a501d49a6a8b684bc83aa6b536f43247d75bacdfTony Wickham            public void run() {
468a501d49a6a8b684bc83aa6b536f43247d75bacdfTony Wickham                mAnim.start();
469a501d49a6a8b684bc83aa6b536f43247d75bacdfTony Wickham            }
470a501d49a6a8b684bc83aa6b536f43247d75bacdfTony Wickham        });
47100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
472716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4737bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void cancelAnimation() {
474456e87e1943ee4e779929f77a9cf11de7af3ec6aVadim Tryshev        mAnimationCancelled = true;
4757bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mAnim != null && mAnim.isRunning()) {
4767bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            mAnim.cancel();
4777bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
4787bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    }
4797bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
48000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
48100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Move the window containing this view.
48200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *
4838dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param touchX the x coordinate the user touched in DragLayer coordinates
4848dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param touchY the y coordinate the user touched in DragLayer coordinates
48500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
4861bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public void move(int touchX, int touchY) {
4874a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        if (touchX > 0 && touchY > 0 && mLastTouchX > 0 && mLastTouchY > 0) {
4884a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            applySpring(mLastTouchX - touchX, mLastTouchY - touchY);
4894a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        }
490a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mLastTouchX = touchX;
491a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mLastTouchY = touchY;
492a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        applyTranslation();
493a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    }
494a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal
495ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham    public void animateTo(int toTouchX, int toTouchY, Runnable onCompleteRunnable, int duration) {
496ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham        mTempLoc[0] = toTouchX - mRegistrationX;
497ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham        mTempLoc[1] = toTouchY - mRegistrationY;
498ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham        mDragLayer.animateViewIntoPosition(this, mTempLoc, 1f, mInitialScale, mInitialScale,
499ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham                DragLayer.ANIMATION_END_DISAPPEAR, onCompleteRunnable, duration);
500ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham    }
501ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham
502a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    public void animateShift(final int shiftX, final int shiftY) {
503a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        if (mAnim.isStarted()) {
504a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal            return;
505a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        }
506a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mAnimatedShiftX = shiftX;
507a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mAnimatedShiftY = shiftY;
508a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        applyTranslation();
509a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mAnim.addUpdateListener(new AnimatorUpdateListener() {
510a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal            @Override
511a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal            public void onAnimationUpdate(ValueAnimator animation) {
512a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal                float fraction = 1 - animation.getAnimatedFraction();
513a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal                mAnimatedShiftX = (int) (fraction * shiftX);
514a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal                mAnimatedShiftY = (int) (fraction * shiftY);
515a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal                applyTranslation();
516a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal            }
517a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        });
518a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    }
519a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal
520a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    private void applyTranslation() {
521a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        setTranslationX(mLastTouchX - mRegistrationX + mAnimatedShiftX);
522a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        setTranslationY(mLastTouchY - mRegistrationY + mAnimatedShiftY);
52300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
52400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
5251bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public void remove() {
5267bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (getParent() != null) {
5277bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            mDragLayer.removeView(DragView.this);
5287bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
5296f13342ffd3f968de9ff86b988621cc91d94adffPatrick Dubroy    }
5303a644ed1ce12554fcdf5c499e959bda986d10551Sunny Goyal
531c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda    public int getBlurSizeOutline() {
532c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda        return mBlurSizeOutline;
533c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda    }
534dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal
535dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal    public float getInitialScale() {
536dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal        return mInitialScale;
537dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal    }
53800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato}
539