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;
2403a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyalimport android.annotation.TargetApi;
25654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Songimport android.content.pm.LauncherActivityInfo;
2600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Bitmap;
2700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Canvas;
2803a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyalimport android.graphics.Color;
29fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyalimport android.graphics.ColorMatrix;
30fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyalimport android.graphics.ColorMatrixColorFilter;
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;
3603a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyalimport android.graphics.drawable.ColorDrawable;
374a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.graphics.drawable.Drawable;
38a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyalimport android.graphics.drawable.InsetDrawable;
3903a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyalimport android.os.Build;
404a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.os.Handler;
414a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.os.Looper;
421a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyalimport android.support.animation.FloatPropertyCompat;
434a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.support.animation.SpringAnimation;
444a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport android.support.animation.SpringForce;
4500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.View;
46a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroyimport android.view.animation.DecelerateInterpolator;
47fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshev
48a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyalimport com.android.launcher3.FastBitmapDrawable;
494a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport com.android.launcher3.ItemInfo;
50fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.Launcher;
51fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.LauncherAnimUtils;
52654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Songimport com.android.launcher3.LauncherAppState;
534a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport com.android.launcher3.LauncherModel;
544a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport com.android.launcher3.LauncherSettings;
55ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickhamimport com.android.launcher3.R;
564a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport com.android.launcher3.Utilities;
57654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Songimport com.android.launcher3.compat.LauncherAppsCompat;
58a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyalimport com.android.launcher3.compat.ShortcutConfigActivityInfo;
594a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Songimport com.android.launcher3.config.FeatureFlags;
6003a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyalimport com.android.launcher3.graphics.IconNormalizer;
61a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyalimport com.android.launcher3.graphics.LauncherIcons;
62a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyalimport com.android.launcher3.shortcuts.DeepShortcutManager;
63a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyalimport com.android.launcher3.shortcuts.ShortcutInfoCompat;
64a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyalimport com.android.launcher3.shortcuts.ShortcutKey;
656c82867a7ea3a95a19d6cec7d1fe164d234d2cb6Tony Wickhamimport com.android.launcher3.util.Themes;
66091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
67a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyalimport com.android.launcher3.widget.PendingAddShortcutInfo;
68fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshev
69fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyalimport java.util.Arrays;
70a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyalimport java.util.List;
71fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
721a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyalpublic class DragView extends View {
731a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal    private static final ColorMatrix sTempMatrix1 = new ColorMatrix();
741a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal    private static final ColorMatrix sTempMatrix2 = new ColorMatrix();
751a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
76a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    public static final int COLOR_CHANGE_DURATION = 120;
77a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    public static final int VIEW_ZOOM_DURATION = 150;
78fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
79091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk static float sDragAlpha = 1f;
807bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
81e29897f503d54866fac279aa366922219d60b834Sunny Goyal    private boolean mDrawBitmap = true;
8200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private Bitmap mBitmap;
83ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    private Bitmap mCrossFadeBitmap;
84316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk Paint mPaint;
85c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda    private final int mBlurSizeOutline;
86d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    private final int mRegistrationX;
87d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    private final int mRegistrationY;
88ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham    private final float mInitialScale;
89ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham    private final int[] mTempLoc = new int[2];
9000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
91b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung    private Point mDragVisualizeOffset = null;
92e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    private Rect mDragRegion = null;
934a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private final Launcher mLauncher;
94d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    private final DragLayer mDragLayer;
9542e28092b336bf89bee94c61e2cd327e1d8ec882Sunny Goyal    @Thunk final DragController mDragController;
96fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen    private boolean mHasDrawn = false;
97091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk float mCrossFadeProgress = 0f;
98456e87e1943ee4e779929f77a9cf11de7af3ec6aVadim Tryshev    private boolean mAnimationCancelled = false;
99a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
100a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy    ValueAnimator mAnim;
101eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    // The intrinsic icon scale factor is the scale factor for a drag icon over the workspace
102eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    // size.  This is ignored for non-icons.
103eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    private float mIntrinsicIconScale = 1f;
10400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
105316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk float[] mCurrentFilter;
106fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal    private ValueAnimator mFilterAnimator;
107fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
108a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    private int mLastTouchX;
109a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    private int mLastTouchY;
110a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    private int mAnimatedShiftX;
111a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    private int mAnimatedShiftY;
112a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal
1134a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    // Below variable only needed IF FeatureFlags.LAUNCHER3_SPRING_ICONS is {@code true}
1141a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal    private Drawable mBgSpringDrawable, mFgSpringDrawable;
1151a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal    private SpringFloatValue mTranslateX, mTranslateY;
1164a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    private Path mScaledMaskPath;
117654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song    private Drawable mBadge;
1181a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal    private ColorMatrixColorFilter mBaseFilter;
1194a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
12000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
12100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Construct the drag view.
12200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * <p>
12300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * The registration point is the point inside our view that the touch events should
12400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * be centered upon.
1258dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param launcher The Launcher instance
12600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * @param bitmap The view that we're dragging around.  We scale it up when we draw it.
12700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * @param registrationX The x coordinate of the registration point.
12800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * @param registrationY The y coordinate of the registration point.
12900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
130157793dda450b69da388b859d1c1a7a1083c4ec9Sunny Goyal    public DragView(Launcher launcher, Bitmap bitmap, int registrationX, int registrationY,
131157793dda450b69da388b859d1c1a7a1083c4ec9Sunny Goyal                    final float initialScale, final float finalScaleDps) {
1328dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        super(launcher);
1334a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        mLauncher = launcher;
1348dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mDragLayer = launcher.getDragLayer();
135d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        mDragController = launcher.getDragController();
13600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
13703a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal        final float scale = (bitmap.getWidth() + finalScaleDps) / bitmap.getWidth();
138a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy
139307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // Set the initial scale to avoid any jumps
140307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        setScaleX(initialScale);
141307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        setScaleY(initialScale);
142307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen
143a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        // Animate the view into the correct position
144cda3bfb2e1d89ad872558dd0a82ae79ca6fe41eaJon Miranda        mAnim = LauncherAnimUtils.ofFloat(0f, 1f);
145a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mAnim.setDuration(VIEW_ZOOM_DURATION);
146a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        mAnim.addUpdateListener(new AnimatorUpdateListener() {
147a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy            @Override
148a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy            public void onAnimationUpdate(ValueAnimator animation) {
149a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy                final float value = (Float) animation.getAnimatedValue();
150a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy
15103a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal                setScaleX(initialScale + (value * (scale - initialScale)));
15203a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal                setScaleY(initialScale + (value * (scale - initialScale)));
153867ca62c0e4b811d46734ff940d59c7a787525c8Winson Chung                if (sDragAlpha != 1f) {
154867ca62c0e4b811d46734ff940d59c7a787525c8Winson Chung                    setAlpha(sDragAlpha * value + (1f - value));
155867ca62c0e4b811d46734ff940d59c7a787525c8Winson Chung                }
156a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy
157a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy                if (getParent() == null) {
158a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy                    animation.cancel();
159a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy                }
160a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy            }
161a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        });
16200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
163d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        mAnim.addListener(new AnimatorListenerAdapter() {
164d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev            @Override
165d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev            public void onAnimationEnd(Animator animation) {
166456e87e1943ee4e779929f77a9cf11de7af3ec6aVadim Tryshev                if (!mAnimationCancelled) {
167456e87e1943ee4e779929f77a9cf11de7af3ec6aVadim Tryshev                    mDragController.onDragViewAnimationEnd();
168456e87e1943ee4e779929f77a9cf11de7af3ec6aVadim Tryshev                }
169d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev            }
170d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        });
171d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev
172157793dda450b69da388b859d1c1a7a1083c4ec9Sunny Goyal        mBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight());
173157793dda450b69da388b859d1c1a7a1083c4ec9Sunny Goyal        setDragRegion(new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()));
17400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
17500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // The point in our scaled bitmap that the touch events are located
176a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        mRegistrationX = registrationX;
177a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        mRegistrationY = registrationY;
17862bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy
179ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham        mInitialScale = initialScale;
180ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham
18162bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy        // Force a measure, because Workspace uses getMeasuredHeight() before the layout pass
18262bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy        int ms = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
18362bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy        measure(ms, ms);
1846cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka        mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
18575deaf3d8f369bd13ea59ec3740324a5cfeb3099Sunny Goyal
186c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda        mBlurSizeOutline = getResources().getDimensionPixelSize(R.dimen.blur_size_medium_outline);
187a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal        setElevation(getResources().getDimension(R.dimen.drag_elevation));
1884a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    }
1894a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
1904a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    /**
191e29897f503d54866fac279aa366922219d60b834Sunny Goyal     * Initialize {@code #mIconDrawable} if the item can be represented using
192e29897f503d54866fac279aa366922219d60b834Sunny Goyal     * an {@link AdaptiveIconDrawable} or {@link FolderAdaptiveIcon}.
1934a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song     */
19403a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal    @TargetApi(Build.VERSION_CODES.O)
1954a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    public void setItemInfo(final ItemInfo info) {
196e24cb63b811e2885a69e7df794e9972cdf5a57b9Hyunyoung Song        if (!(FeatureFlags.LAUNCHER3_SPRING_ICONS && Utilities.ATLEAST_OREO)) {
1974a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            return;
1984a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        }
199a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal        if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
200e29897f503d54866fac279aa366922219d60b834Sunny Goyal                info.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT &&
201e29897f503d54866fac279aa366922219d60b834Sunny Goyal                info.itemType != LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
2024a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            return;
2034a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        }
2044a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        // Load the adaptive icon on a background thread and add the view in ui thread.
2054a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        final Looper workerLooper = LauncherModel.getWorkerLooper();
2064a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        new Handler(workerLooper).postAtFrontOfQueue(new Runnable() {
2074a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            @Override
2084a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            public void run() {
209654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song                LauncherAppState appState = LauncherAppState.getInstance(mLauncher);
210a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                Object[] outObj = new Object[1];
211e29897f503d54866fac279aa366922219d60b834Sunny Goyal                final Drawable dr = getFullDrawable(info, appState, outObj);
212a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal
213654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song                if (dr instanceof AdaptiveIconDrawable) {
214654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song                    int w = mBitmap.getWidth();
215654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song                    int h = mBitmap.getHeight();
2161a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    int blurMargin = (int) mLauncher.getResources()
2171a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                            .getDimension(R.dimen.blur_size_medium_outline) / 2;
2181a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
2191a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    Rect bounds = new Rect(0, 0, w, h);
2201a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    bounds.inset(blurMargin, blurMargin);
2215be75795986da5229ec07ad8eec6a8cf0f7a19a3Sunny Goyal                    // Badge is applied after icon normalization so the bounds for badge should not
2225be75795986da5229ec07ad8eec6a8cf0f7a19a3Sunny Goyal                    // be scaled down due to icon normalization.
2235be75795986da5229ec07ad8eec6a8cf0f7a19a3Sunny Goyal                    Rect badgeBounds = new Rect(bounds);
2245be75795986da5229ec07ad8eec6a8cf0f7a19a3Sunny Goyal                    mBadge = getBadge(info, appState, outObj[0]);
2255be75795986da5229ec07ad8eec6a8cf0f7a19a3Sunny Goyal                    mBadge.setBounds(badgeBounds);
2265be75795986da5229ec07ad8eec6a8cf0f7a19a3Sunny Goyal
2271a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    Utilities.scaleRectAboutCenter(bounds,
2281a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                            IconNormalizer.getInstance(mLauncher).getScale(dr, null, null, null));
229654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song                    AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
2301a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
2311a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    // Shrink very tiny bit so that the clip path is smaller than the original bitmap
2321a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    // that has anti aliased edges and shadows.
2331a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    Rect shrunkBounds = new Rect(bounds);
2341a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    Utilities.scaleRectAboutCenter(shrunkBounds, 0.98f);
2351a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    adaptiveIcon.setBounds(shrunkBounds);
2361a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    final Path mask = adaptiveIcon.getIconMask();
2371a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
2381a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    mTranslateX = new SpringFloatValue(DragView.this,
2391a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                            w * AdaptiveIconDrawable.getExtraInsetFraction());
2401a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    mTranslateY = new SpringFloatValue(DragView.this,
2411a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                            h * AdaptiveIconDrawable.getExtraInsetFraction());
242654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song
2431a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    bounds.inset(
2441a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                            (int) (-bounds.width() * AdaptiveIconDrawable.getExtraInsetFraction()),
2451a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                            (int) (-bounds.height() * AdaptiveIconDrawable.getExtraInsetFraction())
2461a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    );
2471a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    mBgSpringDrawable = adaptiveIcon.getBackground();
248746c6c36b656115076318c353418e3ecae303bbcTony Wickham                    if (mBgSpringDrawable == null) {
249746c6c36b656115076318c353418e3ecae303bbcTony Wickham                        mBgSpringDrawable = new ColorDrawable(Color.TRANSPARENT);
250746c6c36b656115076318c353418e3ecae303bbcTony Wickham                    }
2511a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    mBgSpringDrawable.setBounds(bounds);
2521a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    mFgSpringDrawable = adaptiveIcon.getForeground();
253746c6c36b656115076318c353418e3ecae303bbcTony Wickham                    if (mFgSpringDrawable == null) {
254746c6c36b656115076318c353418e3ecae303bbcTony Wickham                        mFgSpringDrawable = new ColorDrawable(Color.TRANSPARENT);
255746c6c36b656115076318c353418e3ecae303bbcTony Wickham                    }
2561a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    mFgSpringDrawable.setBounds(bounds);
25703a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal
258654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song                    new Handler(Looper.getMainLooper()).post(new Runnable() {
259654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song                        @Override
260654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song                        public void run() {
26103a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal                            // Assign the variable on the UI thread to avoid race conditions.
26203a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal                            mScaledMaskPath = mask;
2632814112998042ccb5bda9501a5ae474f2b2832c6Sunny Goyal
264e29897f503d54866fac279aa366922219d60b834Sunny Goyal                            // Do not draw the background in case of folder as its translucent
265e29897f503d54866fac279aa366922219d60b834Sunny Goyal                            mDrawBitmap = !(dr instanceof FolderAdaptiveIcon);
266e29897f503d54866fac279aa366922219d60b834Sunny Goyal
2672814112998042ccb5bda9501a5ae474f2b2832c6Sunny Goyal                            if (info.isDisabled()) {
2682814112998042ccb5bda9501a5ae474f2b2832c6Sunny Goyal                                FastBitmapDrawable d = new FastBitmapDrawable(null);
2692814112998042ccb5bda9501a5ae474f2b2832c6Sunny Goyal                                d.setIsDisabled(true);
2701a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                                mBaseFilter = (ColorMatrixColorFilter) d.getColorFilter();
2712814112998042ccb5bda9501a5ae474f2b2832c6Sunny Goyal                            }
2721a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                            updateColorFilter();
273654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song                        }
274654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song                    });
275654bf3141bc02604842659f34c15e0fb151a8eaeHyunyoung Song                }
2764a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song            }});
2774a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    }
2784a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song
2791a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal    @TargetApi(Build.VERSION_CODES.O)
2801a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal    private void updateColorFilter() {
2811a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        if (mCurrentFilter == null) {
2821a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            mPaint.setColorFilter(null);
2831a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
2841a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            if (mScaledMaskPath != null) {
2851a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                mBgSpringDrawable.setColorFilter(mBaseFilter);
2861a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                mBgSpringDrawable.setColorFilter(mBaseFilter);
2871a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                mBadge.setColorFilter(mBaseFilter);
2881a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            }
2891a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        } else {
2901a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            ColorMatrixColorFilter currentFilter = new ColorMatrixColorFilter(mCurrentFilter);
2911a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            mPaint.setColorFilter(currentFilter);
2921a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
2931a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            if (mScaledMaskPath != null) {
2941a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                if (mBaseFilter != null) {
2951a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    mBaseFilter.getColorMatrix(sTempMatrix1);
2961a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    sTempMatrix2.set(mCurrentFilter);
2971a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    sTempMatrix1.postConcat(sTempMatrix2);
2981a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
2991a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    currentFilter = new ColorMatrixColorFilter(sTempMatrix1);
3001a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                }
3011a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
3021a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                mBgSpringDrawable.setColorFilter(currentFilter);
3031a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                mFgSpringDrawable.setColorFilter(currentFilter);
3041a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                mBadge.setColorFilter(currentFilter);
3051a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            }
3061a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        }
3071a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
3081a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        invalidate();
3091a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal    }
3101a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
311a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal    /**
312a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal     * Returns the full drawable for {@param info}.
313a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal     * @param outObj this is set to the internal data associated with {@param info},
314a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal     *               eg {@link LauncherActivityInfo} or {@link ShortcutInfoCompat}.
315a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal     */
316a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal    private Drawable getFullDrawable(ItemInfo info, LauncherAppState appState, Object[] outObj) {
317a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal        if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
318a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            LauncherActivityInfo activityInfo = LauncherAppsCompat.getInstance(mLauncher)
319a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                    .resolveActivity(info.getIntent(), info.user);
320a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            outObj[0] = activityInfo;
321a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            return (activityInfo != null) ? appState.getIconCache()
3221da138903bc8412615edacd7a447c6ffc25851d4Sunny Goyal                    .getFullResIcon(activityInfo, false) : null;
323a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal        } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
324a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            if (info instanceof PendingAddShortcutInfo) {
325a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                ShortcutConfigActivityInfo activityInfo =
326a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                        ((PendingAddShortcutInfo) info).activityInfo;
327a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                outObj[0] = activityInfo;
328a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                return activityInfo.getFullResIcon(appState.getIconCache());
329a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            }
330a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            ShortcutKey key = ShortcutKey.fromItemInfo(info);
331a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            DeepShortcutManager sm = DeepShortcutManager.getInstance(mLauncher);
332a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            List<ShortcutInfoCompat> si = sm.queryForFullDetails(
333a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                    key.componentName.getPackageName(), Arrays.asList(key.getId()), key.user);
334a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            if (si.isEmpty()) {
335a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                return null;
336a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            } else {
337a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                outObj[0] = si.get(0);
338a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                return sm.getShortcutIconDrawable(si.get(0),
339a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                        appState.getInvariantDeviceProfile().fillResIconDpi);
340a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            }
341e29897f503d54866fac279aa366922219d60b834Sunny Goyal        } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
342e29897f503d54866fac279aa366922219d60b834Sunny Goyal            FolderAdaptiveIcon icon =  FolderAdaptiveIcon.createFolderAdaptiveIcon(
343e29897f503d54866fac279aa366922219d60b834Sunny Goyal                    mLauncher, info.id, new Point(mBitmap.getWidth(), mBitmap.getHeight()));
344e29897f503d54866fac279aa366922219d60b834Sunny Goyal            if (icon == null) {
345e29897f503d54866fac279aa366922219d60b834Sunny Goyal                return null;
346e29897f503d54866fac279aa366922219d60b834Sunny Goyal            }
347e29897f503d54866fac279aa366922219d60b834Sunny Goyal            outObj[0] = icon;
348e29897f503d54866fac279aa366922219d60b834Sunny Goyal            return icon;
349a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal        } else {
350a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            return null;
351a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal        }
352a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal    }
353a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal
354a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal    /**
355a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal     * For apps icons and shortcut icons that have badges, this method creates a drawable that can
356a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal     * later on be rendered on top of the layers for the badges. For app icons, work profile badges
357a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal     * can only be applied. For deep shortcuts, when dragged from the pop up container, there's no
358a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal     * badge. When dragged from workspace or folder, it may contain app AND/OR work profile badge
359a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal     **/
360a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal
361a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal    @TargetApi(Build.VERSION_CODES.O)
362a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal    private Drawable getBadge(ItemInfo info, LauncherAppState appState, Object obj) {
363a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal        int iconSize = appState.getInvariantDeviceProfile().iconBitmapSize;
364a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal        if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
365a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            if (info.id == ItemInfo.NO_ID || !(obj instanceof ShortcutInfoCompat)) {
366a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                // The item is not yet added on home screen.
367a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                return new FixedSizeEmptyDrawable(iconSize);
368a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            }
369a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            ShortcutInfoCompat si = (ShortcutInfoCompat) obj;
370a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            Bitmap badge = LauncherIcons.getShortcutInfoBadge(si, appState.getIconCache());
371a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal
372a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            float badgeSize = mLauncher.getResources().getDimension(R.dimen.profile_badge_size);
373a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            float insetFraction = (iconSize - badgeSize) / iconSize;
374a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            return new InsetDrawable(new FastBitmapDrawable(badge),
375a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                    insetFraction, insetFraction, 0, 0);
376e29897f503d54866fac279aa366922219d60b834Sunny Goyal        } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
377e29897f503d54866fac279aa366922219d60b834Sunny Goyal            return ((FolderAdaptiveIcon) obj).getBadge();
378a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal        } else {
379a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal            return mLauncher.getPackageManager()
380a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal                    .getUserBadgedIcon(new FixedSizeEmptyDrawable(iconSize), info.user);
381a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal        }
382a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal    }
383a2fde430b53c78255ea2cc87308897a06afb6723Sunny Goyal
3844a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    @Override
3854a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
3861a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        setMeasuredDimension(mBitmap.getWidth(), mBitmap.getHeight());
38762bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy    }
38862bbb3c573fe902940431e4b957c0c4918358d36Patrick Dubroy
389eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    /** Sets the scale of the view over the normal workspace icon size. */
390eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    public void setIntrinsicIconScaleFactor(float scale) {
391eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung        mIntrinsicIconScale = scale;
392eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    }
393eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung
394eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    public float getIntrinsicIconScaleFactor() {
395eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung        return mIntrinsicIconScale;
396eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    }
397eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung
398a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    public int getDragRegionLeft() {
399e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        return mDragRegion.left;
400a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
401a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
402a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    public int getDragRegionTop() {
403e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        return mDragRegion.top;
404a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
405a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
406a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    public int getDragRegionWidth() {
407e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        return mDragRegion.width();
408a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
409a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
410a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    public int getDragRegionHeight() {
411e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        return mDragRegion.height();
412e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    }
413e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen
414b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung    public void setDragVisualizeOffset(Point p) {
415b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung        mDragVisualizeOffset = p;
416b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung    }
417b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung
418b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung    public Point getDragVisualizeOffset() {
419b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung        return mDragVisualizeOffset;
420b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung    }
421b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung
422e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    public void setDragRegion(Rect r) {
423e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        mDragRegion = r;
424e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    }
425e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen
426e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    public Rect getDragRegion() {
427e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        return mDragRegion;
428a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
429a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
43000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    @Override
43100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    protected void onDraw(Canvas canvas) {
432fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        mHasDrawn = true;
433e29897f503d54866fac279aa366922219d60b834Sunny Goyal
434e29897f503d54866fac279aa366922219d60b834Sunny Goyal        if (mDrawBitmap) {
435e29897f503d54866fac279aa366922219d60b834Sunny Goyal            // Always draw the bitmap to mask anti aliasing due to clipPath
436e29897f503d54866fac279aa366922219d60b834Sunny Goyal            boolean crossFade = mCrossFadeProgress > 0 && mCrossFadeBitmap != null;
437e29897f503d54866fac279aa366922219d60b834Sunny Goyal            if (crossFade) {
438e29897f503d54866fac279aa366922219d60b834Sunny Goyal                int alpha = crossFade ? (int) (255 * (1 - mCrossFadeProgress)) : 255;
439e29897f503d54866fac279aa366922219d60b834Sunny Goyal                mPaint.setAlpha(alpha);
440e29897f503d54866fac279aa366922219d60b834Sunny Goyal            }
441e29897f503d54866fac279aa366922219d60b834Sunny Goyal            canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
442e29897f503d54866fac279aa366922219d60b834Sunny Goyal            if (crossFade) {
443e29897f503d54866fac279aa366922219d60b834Sunny Goyal                mPaint.setAlpha((int) (255 * mCrossFadeProgress));
444e29897f503d54866fac279aa366922219d60b834Sunny Goyal                final int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
445e29897f503d54866fac279aa366922219d60b834Sunny Goyal                float sX = (mBitmap.getWidth() * 1.0f) / mCrossFadeBitmap.getWidth();
446e29897f503d54866fac279aa366922219d60b834Sunny Goyal                float sY = (mBitmap.getHeight() * 1.0f) / mCrossFadeBitmap.getHeight();
447e29897f503d54866fac279aa366922219d60b834Sunny Goyal                canvas.scale(sX, sY);
448e29897f503d54866fac279aa366922219d60b834Sunny Goyal                canvas.drawBitmap(mCrossFadeBitmap, 0.0f, 0.0f, mPaint);
449e29897f503d54866fac279aa366922219d60b834Sunny Goyal                canvas.restoreToCount(saveCount);
450e29897f503d54866fac279aa366922219d60b834Sunny Goyal            }
451ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        }
4521a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
4531a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        if (mScaledMaskPath != null) {
4541a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            int cnt = canvas.save();
4551a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            canvas.clipPath(mScaledMaskPath);
4561a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            mBgSpringDrawable.draw(canvas);
4571a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            canvas.translate(mTranslateX.mValue, mTranslateY.mValue);
4581a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            mFgSpringDrawable.draw(canvas);
4591a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            canvas.restoreToCount(cnt);
4601a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            mBadge.draw(canvas);
4611a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        }
462ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
463ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
464ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public void setCrossFadeBitmap(Bitmap crossFadeBitmap) {
465ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        mCrossFadeBitmap = crossFadeBitmap;
466ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
467ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
468ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public void crossFade(int duration) {
469cda3bfb2e1d89ad872558dd0a82ae79ca6fe41eaJon Miranda        ValueAnimator va = LauncherAnimUtils.ofFloat(0f, 1f);
470ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        va.setDuration(duration);
471ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        va.setInterpolator(new DecelerateInterpolator(1.5f));
472ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        va.addUpdateListener(new AnimatorUpdateListener() {
473ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            @Override
474ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
475ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                mCrossFadeProgress = animation.getAnimatedFraction();
4765d2fc32e6da66f877dfba4fe513fbabdcdae5f99Sunny Goyal                invalidate();
477ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            }
478ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        });
479ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        va.start();
48000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
48100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
48261967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung    public void setColor(int color) {
4836cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka        if (mPaint == null) {
4846cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka            mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
4856cfafb96c3b108fec90897c1a251229be9861ddbMichael Jurka        }
48661967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        if (color != 0) {
487fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            ColorMatrix m1 = new ColorMatrix();
488fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            m1.setSaturation(0);
489fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
490fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            ColorMatrix m2 = new ColorMatrix();
4916c82867a7ea3a95a19d6cec7d1fe164d234d2cb6Tony Wickham            Themes.setColorScaleOnMatrix(color, m2);
492fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            m1.postConcat(m2);
493fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
494a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            animateFilterTo(m1.getArray());
49561967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        } else {
496a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal            if (mCurrentFilter == null) {
4971a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                updateColorFilter();
498fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            } else {
499fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal                animateFilterTo(new ColorMatrix().getArray());
500fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            }
50161967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        }
502fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal    }
503fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
504fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal    private void animateFilterTo(float[] targetFilter) {
505fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        float[] oldFilter = mCurrentFilter == null ? new ColorMatrix().getArray() : mCurrentFilter;
506fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        mCurrentFilter = Arrays.copyOf(oldFilter, oldFilter.length);
507fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
508fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        if (mFilterAnimator != null) {
509fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            mFilterAnimator.cancel();
510fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        }
511fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        mFilterAnimator = ValueAnimator.ofObject(new FloatArrayEvaluator(mCurrentFilter),
512fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal                oldFilter, targetFilter);
513fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        mFilterAnimator.setDuration(COLOR_CHANGE_DURATION);
514fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        mFilterAnimator.addUpdateListener(new AnimatorUpdateListener() {
515fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal
516fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            @Override
517fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            public void onAnimationUpdate(ValueAnimator animation) {
5181a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                updateColorFilter();
519fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal            }
520fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        });
521fe0d1f2458e6a442613b070ae549124a4780e759Sunny Goyal        mFilterAnimator.start();
52200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
52300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
524fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen    public boolean hasDrawn() {
525fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        return mHasDrawn;
526fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen    }
527fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen
5283e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    @Override
5293e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    public void setAlpha(float alpha) {
5303e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        super.setAlpha(alpha);
5313e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mPaint.setAlpha((int) (255 * alpha));
5323e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        invalidate();
5333e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    }
5343e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
53500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
53600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Create a window containing this view and show it.
53700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *
5388dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param touchX the x coordinate the user touched in DragLayer coordinates
5398dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param touchY the y coordinate the user touched in DragLayer coordinates
54000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
5418dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    public void show(int touchX, int touchY) {
5428dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mDragLayer.addView(this);
543043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
544043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Start the pick-up animation
5458dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        DragLayer.LayoutParams lp = new DragLayer.LayoutParams(0, 0);
5468dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        lp.width = mBitmap.getWidth();
5478dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        lp.height = mBitmap.getHeight();
5488dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        lp.customPosition = true;
5498dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        setLayoutParams(lp);
550a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        move(touchX, touchY);
551ca99383daef92fed673de22126875cb485be494fMichael Jurka        // Post the animation to skip other expensive work happening on the first frame
552ca99383daef92fed673de22126875cb485be494fMichael Jurka        post(new Runnable() {
553a501d49a6a8b684bc83aa6b536f43247d75bacdfTony Wickham            public void run() {
554a501d49a6a8b684bc83aa6b536f43247d75bacdfTony Wickham                mAnim.start();
555a501d49a6a8b684bc83aa6b536f43247d75bacdfTony Wickham            }
556a501d49a6a8b684bc83aa6b536f43247d75bacdfTony Wickham        });
55700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
558716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
5597bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void cancelAnimation() {
560456e87e1943ee4e779929f77a9cf11de7af3ec6aVadim Tryshev        mAnimationCancelled = true;
5617bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mAnim != null && mAnim.isRunning()) {
5627bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            mAnim.cancel();
5637bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
5647bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    }
5657bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
56600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
56700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Move the window containing this view.
56800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *
5698dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param touchX the x coordinate the user touched in DragLayer coordinates
5708dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param touchY the y coordinate the user touched in DragLayer coordinates
57100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
5721bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public void move(int touchX, int touchY) {
5731a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        if (touchX > 0 && touchY > 0 && mLastTouchX > 0 && mLastTouchY > 0
5741a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                && mScaledMaskPath != null) {
5751a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            mTranslateX.animateToPos(mLastTouchX - touchX);
5761a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            mTranslateY.animateToPos(mLastTouchY - touchY);
5774a5fd100d743fcd9e51c2da36a9f9f542c5b5cddHyunyoung Song        }
578a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mLastTouchX = touchX;
579a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mLastTouchY = touchY;
580a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        applyTranslation();
581a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    }
582a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal
583ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham    public void animateTo(int toTouchX, int toTouchY, Runnable onCompleteRunnable, int duration) {
584ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham        mTempLoc[0] = toTouchX - mRegistrationX;
585ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham        mTempLoc[1] = toTouchY - mRegistrationY;
586ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham        mDragLayer.animateViewIntoPosition(this, mTempLoc, 1f, mInitialScale, mInitialScale,
587ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham                DragLayer.ANIMATION_END_DISAPPEAR, onCompleteRunnable, duration);
588ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham    }
589ea62fe0be19c54f8fbb434c6334418b96626f70dTony Wickham
590a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    public void animateShift(final int shiftX, final int shiftY) {
591a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        if (mAnim.isStarted()) {
592a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal            return;
593a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        }
594a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mAnimatedShiftX = shiftX;
595a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mAnimatedShiftY = shiftY;
596a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        applyTranslation();
597a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        mAnim.addUpdateListener(new AnimatorUpdateListener() {
598a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal            @Override
599a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal            public void onAnimationUpdate(ValueAnimator animation) {
600a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal                float fraction = 1 - animation.getAnimatedFraction();
601a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal                mAnimatedShiftX = (int) (fraction * shiftX);
602a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal                mAnimatedShiftY = (int) (fraction * shiftY);
603a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal                applyTranslation();
604a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal            }
605a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        });
606a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    }
607a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal
608a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal    private void applyTranslation() {
609a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        setTranslationX(mLastTouchX - mRegistrationX + mAnimatedShiftX);
610a2454ad2d8dcffa94f670853eb464726c73597f1Sunny Goyal        setTranslationY(mLastTouchY - mRegistrationY + mAnimatedShiftY);
61100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
61200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
6131bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    public void remove() {
6147bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (getParent() != null) {
6157bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            mDragLayer.removeView(DragView.this);
6167bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
6176f13342ffd3f968de9ff86b988621cc91d94adffPatrick Dubroy    }
6183a644ed1ce12554fcdf5c499e959bda986d10551Sunny Goyal
619c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda    public int getBlurSizeOutline() {
620c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda        return mBlurSizeOutline;
621c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda    }
622dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal
623dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal    public float getInitialScale() {
624dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal        return mInitialScale;
625dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal    }
62603a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal
6271a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal    private static class SpringFloatValue {
6281a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
6291a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        private static final FloatPropertyCompat<SpringFloatValue> VALUE =
6301a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                new FloatPropertyCompat<SpringFloatValue>("value") {
6311a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    @Override
6321a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    public float getValue(SpringFloatValue object) {
6331a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                        return object.mValue;
6341a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    }
6351a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
6361a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    @Override
6371a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    public void setValue(SpringFloatValue object, float value) {
6381a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                        object.mValue = value;
6391a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                        object.mView.invalidate();
6401a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    }
6411a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                };
6421a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
6431a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        // Following three values are fine tuned with motion ux designer
6441a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        private final static int STIFFNESS = 4000;
6451a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        private final static float DAMPENING_RATIO = 1f;
6461a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        private final static int PARALLAX_MAX_IN_DP = 8;
6471a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
6481a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        private final View mView;
6491a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        private final SpringAnimation mSpring;
6501a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        private final float mDelta;
6511a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
6521a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        private float mValue;
6531a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
6541a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        public SpringFloatValue(View view, float range) {
6551a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            mView = view;
6561a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            mSpring = new SpringAnimation(this, VALUE, 0)
6571a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    .setMinValue(-range).setMaxValue(range)
6581a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                    .setSpring(new SpringForce(0)
6591a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                            .setDampingRatio(DAMPENING_RATIO)
6601a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal                            .setStiffness(STIFFNESS));
6611a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            mDelta = view.getResources().getDisplayMetrics().density * PARALLAX_MAX_IN_DP;
6621a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        }
6631a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
6641a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        public void animateToPos(float value) {
6651a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal            mSpring.animateToFinalPosition(Utilities.boundToRange(value, -mDelta, mDelta));
6661a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal        }
6671a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal    }
6681a56a5286c65bd56a5000001eed06b01d372c9a9Sunny Goyal
66903a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal    private static class FixedSizeEmptyDrawable extends ColorDrawable {
67003a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal
67103a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal        private final int mSize;
67203a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal
67303a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal        public FixedSizeEmptyDrawable(int size) {
67403a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal            super(Color.TRANSPARENT);
67503a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal            mSize = size;
67603a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal        }
67703a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal
67803a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal        @Override
67903a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal        public int getIntrinsicHeight() {
68003a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal            return mSize;
68103a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal        }
68203a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal
68303a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal        @Override
68403a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal        public int getIntrinsicWidth() {
68503a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal            return mSize;
68603a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal        }
68703a38a669cc01123858c309c5536c0c8d86bb831Sunny Goyal    }
68800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato}
689