DragLayer.java revision 8b805b17158886035b38261eb611d8641701ae43
131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License.
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License.
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17a5902524d4403885eb4c50360bf3465c6be796efJoe Onoratopackage com.android.launcher2;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.Animator;
20716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.AnimatorListenerAdapter;
21716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.TimeInterpolator;
22716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator;
23716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator.AnimatorUpdateListener;
2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
25716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.content.res.Resources;
266788269814a678af976dfc7d6135993e172ce586Adam Cohenimport android.graphics.Rect;
2731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
2831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.KeyEvent;
290e26059548e429e5d1c973bebe4c561bead2926fMichael Jurkaimport android.view.MotionEvent;
30ea3763c2672f77539538af8cdd395ad97058eaabRomain Guyimport android.view.View;
318b805b17158886035b38261eb611d8641701ae43Michael Jurkaimport android.view.ViewGroup;
3276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.ViewParent;
333371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityEvent;
343371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityManager;
35716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.view.animation.DecelerateInterpolator;
363e8f811f31a2275e778244427271f77f4116c08bAdam Cohenimport android.view.animation.Interpolator;
3731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.FrameLayout;
38ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohenimport android.widget.TextView;
3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
40716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport com.android.launcher.R;
41716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
421d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohenimport java.util.ArrayList;
436788269814a678af976dfc7d6135993e172ce586Adam Cohen
4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
450e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * A ViewGroup that coordinates dragging across its descendants
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
478b805b17158886035b38261eb611d8641701ae43Michael Jurkapublic class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChangeListener {
48120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    private DragController mDragController;
49120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    private int[] mTmpXY = new int[2];
5031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
51716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private int mXDown, mYDown;
52716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private Launcher mLauncher;
53716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
546788269814a678af976dfc7d6135993e172ce586Adam Cohen    // Variables relating to resizing widgets
556788269814a678af976dfc7d6135993e172ce586Adam Cohen    private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
566788269814a678af976dfc7d6135993e172ce586Adam Cohen            new ArrayList<AppWidgetResizeFrame>();
576788269814a678af976dfc7d6135993e172ce586Adam Cohen    private AppWidgetResizeFrame mCurrentResizeFrame;
58716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
59716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    // Variables relating to animation of views after drop
60716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private ValueAnimator mDropAnim = null;
618dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private ValueAnimator mFadeOutAnim = null;
628dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
637bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    private DragView mDropView = null;
646441de0ec2a71862798dd51180d0811b42edd514Adam Cohen    private int mAnchorViewInitialScrollX = 0;
656441de0ec2a71862798dd51180d0811b42edd514Adam Cohen    private View mAnchorView = null;
668dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
673371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean mHoverPointClosesFolder = false;
683371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private Rect mHitRect = new Rect();
6921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    private int mWorkspaceIndex = -1;
70ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen    private int mQsbIndex = -1;
71ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_DISAPPEAR = 0;
72ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_FADE_OUT = 1;
73ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
746788269814a678af976dfc7d6135993e172ce586Adam Cohen
7531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
7631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to create a new DragLayer from XML.
7731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
7831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
790e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
8031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public DragLayer(Context context, AttributeSet attrs) {
8231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs);
83be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung
84be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        // Disable multitouch across the workspace/all apps/customize tray
85be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        setMotionEventSplittingEnabled(false);
8621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        setChildrenDrawingOrderEnabled(true);
878b805b17158886035b38261eb611d8641701ae43Michael Jurka        setOnHierarchyChangeListener(this);
8831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
8931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
904c98d9235d164680186180974719f551cf935d08Winson Chung    public void setup(Launcher launcher, DragController controller) {
914c98d9235d164680186180974719f551cf935d08Winson Chung        mLauncher = launcher;
9200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = controller;
9331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
9476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
9631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean dispatchKeyEvent(KeyEvent event) {
9700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
9831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1003371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
1013371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect);
1023371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
1033371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return true;
1043371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
1053371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
1063371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1073371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
1083371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
1093371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        getDescendantRectRelativeToSelf(folder, mHitRect);
1103371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
1113371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return true;
1123371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
1133371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
1143371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1153371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
11676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
1176788269814a678af976dfc7d6135993e172ce586Adam Cohen        Rect hitRect = new Rect();
1186788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
1196788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
1206788269814a678af976dfc7d6135993e172ce586Adam Cohen
1216788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (AppWidgetResizeFrame child: mResizeFrames) {
1226788269814a678af976dfc7d6135993e172ce586Adam Cohen            child.getHitRect(hitRect);
1236788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (hitRect.contains(x, y)) {
1246788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
1256788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = child;
1266788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mXDown = x;
1276788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mYDown = y;
1286788269814a678af976dfc7d6135993e172ce586Adam Cohen                    requestDisallowInterceptTouchEvent(true);
1296788269814a678af976dfc7d6135993e172ce586Adam Cohen                    return true;
1306788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
1316788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
1326788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
13376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
1341d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
1357d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung        if (currentFolder != null && !mLauncher.isFolderClingVisible() && intercept) {
1361d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen            if (currentFolder.isEditingName()) {
1373371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                if (!isEventOverFolderTextRegion(currentFolder, ev)) {
1381d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen                    currentFolder.dismissEditingName();
13976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                    return true;
1402801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                }
1412801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            }
14276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
1431d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen            getDescendantRectRelativeToSelf(currentFolder, hitRect);
1443371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            if (!isEventOverFolder(currentFolder, ev)) {
14576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                mLauncher.closeFolder();
14676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                return true;
14776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            }
1482801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
1496788269814a678af976dfc7d6135993e172ce586Adam Cohen        return false;
1506788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
1516788269814a678af976dfc7d6135993e172ce586Adam Cohen
15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
15331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onInterceptTouchEvent(MotionEvent ev) {
1546788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
15576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            if (handleTouchDown(ev, true)) {
1566788269814a678af976dfc7d6135993e172ce586Adam Cohen                return true;
157d1837cc69eb222371afdd30890f7215d117510f2Patrick Dubroy            }
1581b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen        }
1596788269814a678af976dfc7d6135993e172ce586Adam Cohen        clearAllResizeFrames();
1604db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato        return mDragController.onInterceptTouchEvent(ev);
16131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
16231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
1643371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onInterceptHoverEvent(MotionEvent ev) {
1653371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
1663371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (currentFolder == null) {
1673371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return false;
1683371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        } else {
1698b805b17158886035b38261eb611d8641701ae43Michael Jurka                AccessibilityManager accessibilityManager = (AccessibilityManager)
1708b805b17158886035b38261eb611d8641701ae43Michael Jurka                        getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
1718b805b17158886035b38261eb611d8641701ae43Michael Jurka            if (accessibilityManager.isTouchExplorationEnabled()) {
1723371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                final int action = ev.getAction();
1733371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                boolean isOverFolder;
1743371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                switch (action) {
1753371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_ENTER:
1763371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        isOverFolder = isEventOverFolder(currentFolder, ev);
1773371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        if (!isOverFolder) {
1783371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
1793371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
1803371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
1813371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else if (isOverFolder) {
1823371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = false;
1833371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else {
1843371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
1853371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
1863371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_MOVE:
1873371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        isOverFolder = isEventOverFolder(currentFolder, ev);
1883371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        if (!isOverFolder && !mHoverPointClosesFolder) {
1893371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
1903371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
1913371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
1923371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else if (isOverFolder) {
1933371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = false;
1943371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else {
1953371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
1963371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
1973371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                }
1983371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            }
1993371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
2003371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
2013371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2023371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2033371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private void sendTapOutsideFolderAccessibilityEvent(boolean isEditingName) {
2048b805b17158886035b38261eb611d8641701ae43Michael Jurka        AccessibilityManager accessibilityManager = (AccessibilityManager)
2058b805b17158886035b38261eb611d8641701ae43Michael Jurka                getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
2068b805b17158886035b38261eb611d8641701ae43Michael Jurka        if (accessibilityManager.isEnabled()) {
2073371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close;
2083371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            AccessibilityEvent event = AccessibilityEvent.obtain(
2093371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    AccessibilityEvent.TYPE_VIEW_FOCUSED);
2103371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            onInitializeAccessibilityEvent(event);
2118b805b17158886035b38261eb611d8641701ae43Michael Jurka            event.getText().add(getContext().getString(stringId));
2128b805b17158886035b38261eb611d8641701ae43Michael Jurka            accessibilityManager.sendAccessibilityEvent(event);
2133371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
2143371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2153371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2163371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
2173371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onHoverEvent(MotionEvent ev) {
2183371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // If we've received this, we've already done the necessary handling
2193371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // in onInterceptHoverEvent. Return true to consume the event.
2203371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
2213371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2223371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2233371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
22431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
2256788269814a678af976dfc7d6135993e172ce586Adam Cohen        boolean handled = false;
2266788269814a678af976dfc7d6135993e172ce586Adam Cohen        int action = ev.getAction();
2276788269814a678af976dfc7d6135993e172ce586Adam Cohen
2286788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
2296788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
2306788269814a678af976dfc7d6135993e172ce586Adam Cohen
2316788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
2326788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
23376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                if (handleTouchDown(ev, false)) {
2346788269814a678af976dfc7d6135993e172ce586Adam Cohen                    return true;
2356788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
2366788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
2376788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
2386788269814a678af976dfc7d6135993e172ce586Adam Cohen
2396788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mCurrentResizeFrame != null) {
2406788269814a678af976dfc7d6135993e172ce586Adam Cohen            handled = true;
2416788269814a678af976dfc7d6135993e172ce586Adam Cohen            switch (action) {
2426788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_MOVE:
2436788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
2446788269814a678af976dfc7d6135993e172ce586Adam Cohen                    break;
2456788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_CANCEL:
2466788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_UP:
247bebf042666cffe52039b875a549a582abd78a431Adam Cohen                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
248bebf042666cffe52039b875a549a582abd78a431Adam Cohen                    mCurrentResizeFrame.onTouchUp();
2496788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = null;
2506788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
2516788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
2526788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (handled) return true;
2534db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato        return mDragController.onTouchEvent(ev);
25491a9c9636f10f1e12cd1f660b2e330634fbdc7dcRomain Guy    }
255ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
25635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
25735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Determine the rect of the descendant in this DragLayer's coordinates
25835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
25935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant whose coordinates we want to find.
26035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param r The rect into which to place the results.
26135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer.
26235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
263ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen    public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
264716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[0] = 0;
265716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[1] = 0;
266ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
2678dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        r.set(mTmpXY[0], mTmpXY[1],
2688dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                mTmpXY[0] + descendant.getWidth(), mTmpXY[1] + descendant.getHeight());
269ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        return scale;
270716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
27176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
27235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    public void getLocationInDragLayer(View child, int[] loc) {
27335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[0] = 0;
27435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[1] = 0;
27535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        getDescendantCoordRelativeToSelf(child, loc);
27635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    }
27735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen
27835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
27935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's
28035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * coordinates.
28135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
28235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant to which the passed coordinate is relative.
28335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param coord The coordinate that we want mapped.
28435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer.
28535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
286b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
287557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float scale = 1.0f;
288557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float[] pt = {coord[0], coord[1]};
289557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        descendant.getMatrix().mapPoints(pt);
290557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        scale *= descendant.getScaleX();
291557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        pt[0] += descendant.getLeft();
292557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        pt[1] += descendant.getTop();
29376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        ViewParent viewParent = descendant.getParent();
29476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        while (viewParent instanceof View && viewParent != this) {
29576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            final View view = (View)viewParent;
296557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            view.getMatrix().mapPoints(pt);
297557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            scale *= view.getScaleX();
298557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            pt[0] += view.getLeft() - view.getScrollX();
299557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            pt[1] += view.getTop() - view.getScrollY();
30076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            viewParent = view.getParent();
30176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        }
302fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        coord[0] = (int) Math.round(pt[0]);
303fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        coord[1] = (int) Math.round(pt[1]);
304557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        return scale;
30576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
30676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
3073e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    public void getViewRectRelativeToSelf(View v, Rect r) {
3083e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int[] loc = new int[2];
3098dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        getLocationInWindow(loc);
3103e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int x = loc[0];
3113e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int y = loc[1];
312716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
3138dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        v.getLocationInWindow(loc);
3143e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vX = loc[0];
3153e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vY = loc[1];
316716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
3173e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int left = vX - x;
3183e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int top = vY - y;
3193e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
320716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
321716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
322ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    @Override
323ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    public boolean dispatchUnhandledMove(View focused, int direction) {
324ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        return mDragController.dispatchUnhandledMove(focused, direction);
325ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
326120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen
3276788269814a678af976dfc7d6135993e172ce586Adam Cohen    public static class LayoutParams extends FrameLayout.LayoutParams {
3286788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int x, y;
3296788269814a678af976dfc7d6135993e172ce586Adam Cohen        public boolean customPosition = false;
3306788269814a678af976dfc7d6135993e172ce586Adam Cohen
3316788269814a678af976dfc7d6135993e172ce586Adam Cohen        /**
3326788269814a678af976dfc7d6135993e172ce586Adam Cohen         * {@inheritDoc}
3336788269814a678af976dfc7d6135993e172ce586Adam Cohen         */
3346788269814a678af976dfc7d6135993e172ce586Adam Cohen        public LayoutParams(int width, int height) {
3356788269814a678af976dfc7d6135993e172ce586Adam Cohen            super(width, height);
3366788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3376788269814a678af976dfc7d6135993e172ce586Adam Cohen
3386788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setWidth(int width) {
3396788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.width = width;
3406788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3416788269814a678af976dfc7d6135993e172ce586Adam Cohen
3426788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getWidth() {
3436788269814a678af976dfc7d6135993e172ce586Adam Cohen            return width;
3446788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3456788269814a678af976dfc7d6135993e172ce586Adam Cohen
3466788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setHeight(int height) {
3476788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.height = height;
3486788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3496788269814a678af976dfc7d6135993e172ce586Adam Cohen
3506788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getHeight() {
3516788269814a678af976dfc7d6135993e172ce586Adam Cohen            return height;
3526788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3536788269814a678af976dfc7d6135993e172ce586Adam Cohen
3546788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setX(int x) {
3556788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.x = x;
3566788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3576788269814a678af976dfc7d6135993e172ce586Adam Cohen
3586788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getX() {
3596788269814a678af976dfc7d6135993e172ce586Adam Cohen            return x;
3606788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3616788269814a678af976dfc7d6135993e172ce586Adam Cohen
3626788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setY(int y) {
3636788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.y = y;
3646788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3656788269814a678af976dfc7d6135993e172ce586Adam Cohen
3666788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getY() {
3676788269814a678af976dfc7d6135993e172ce586Adam Cohen            return y;
3686788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3696788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
3706788269814a678af976dfc7d6135993e172ce586Adam Cohen
3716788269814a678af976dfc7d6135993e172ce586Adam Cohen    protected void onLayout(boolean changed, int l, int t, int r, int b) {
3726788269814a678af976dfc7d6135993e172ce586Adam Cohen        super.onLayout(changed, l, t, r, b);
3736788269814a678af976dfc7d6135993e172ce586Adam Cohen        int count = getChildCount();
3746788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (int i = 0; i < count; i++) {
3756788269814a678af976dfc7d6135993e172ce586Adam Cohen            View child = getChildAt(i);
3766788269814a678af976dfc7d6135993e172ce586Adam Cohen            final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
3776788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (flp instanceof LayoutParams) {
3786788269814a678af976dfc7d6135993e172ce586Adam Cohen                final LayoutParams lp = (LayoutParams) flp;
3796788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (lp.customPosition) {
3806788269814a678af976dfc7d6135993e172ce586Adam Cohen                    child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
3816788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
3826788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
3836788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3846788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
3856788269814a678af976dfc7d6135993e172ce586Adam Cohen
3866788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void clearAllResizeFrames() {
3876788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mResizeFrames.size() > 0) {
3886788269814a678af976dfc7d6135993e172ce586Adam Cohen            for (AppWidgetResizeFrame frame: mResizeFrames) {
389bebf042666cffe52039b875a549a582abd78a431Adam Cohen                frame.commitResize();
3906788269814a678af976dfc7d6135993e172ce586Adam Cohen                removeView(frame);
3916788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
3926788269814a678af976dfc7d6135993e172ce586Adam Cohen            mResizeFrames.clear();
3936788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3946788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
3956788269814a678af976dfc7d6135993e172ce586Adam Cohen
3966788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean hasResizeFrames() {
3976788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mResizeFrames.size() > 0;
3986788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
3996788269814a678af976dfc7d6135993e172ce586Adam Cohen
4006788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean isWidgetBeingResized() {
4016788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mCurrentResizeFrame != null;
4026788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
4036788269814a678af976dfc7d6135993e172ce586Adam Cohen
4046788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
4056788269814a678af976dfc7d6135993e172ce586Adam Cohen            CellLayout cellLayout) {
4066788269814a678af976dfc7d6135993e172ce586Adam Cohen        AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
4073a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka                widget, cellLayout, this);
4086788269814a678af976dfc7d6135993e172ce586Adam Cohen
4096788269814a678af976dfc7d6135993e172ce586Adam Cohen        LayoutParams lp = new LayoutParams(-1, -1);
4106788269814a678af976dfc7d6135993e172ce586Adam Cohen        lp.customPosition = true;
4116788269814a678af976dfc7d6135993e172ce586Adam Cohen
4126788269814a678af976dfc7d6135993e172ce586Adam Cohen        addView(resizeFrame, lp);
4136788269814a678af976dfc7d6135993e172ce586Adam Cohen        mResizeFrames.add(resizeFrame);
4146788269814a678af976dfc7d6135993e172ce586Adam Cohen
4156788269814a678af976dfc7d6135993e172ce586Adam Cohen        resizeFrame.snapToWidget(false);
4166788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
417716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
418716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    public void animateViewIntoPosition(DragView dragView, final View child) {
419557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        animateViewIntoPosition(dragView, child, null);
420557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    }
421ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen
4227bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
4237bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
4247bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            int duration) {
425b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        Rect r = new Rect();
426b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        getViewRectRelativeToSelf(dragView, r);
427b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromX = r.left;
428b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromY = r.top;
429b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen
4307bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], alpha, 1, 1, scaleX, scaleY,
431ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                onFinishRunnable, animationEndStyle, duration, null);
432ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
433ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
434557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    public void animateViewIntoPosition(DragView dragView, final View child,
435557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            final Runnable onFinishAnimationRunnable) {
4366441de0ec2a71862798dd51180d0811b42edd514Adam Cohen        animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, null);
437ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    }
438ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen
439ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    public void animateViewIntoPosition(DragView dragView, final View child, int duration,
4406441de0ec2a71862798dd51180d0811b42edd514Adam Cohen            final Runnable onFinishAnimationRunnable, View anchorView) {
441a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka        ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent();
442eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung        CellLayout parent = (CellLayout) (CellLayout) parentChildren.getParent();
443716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        CellLayout.LayoutParams lp =  (CellLayout.LayoutParams) child.getLayoutParams();
444eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung        parentChildren.measureChild(child);
445716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4463e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect r = new Rect();
4473e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        getViewRectRelativeToSelf(dragView, r);
448716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
449716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        int coord[] = new int[2];
450ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        coord[0] = lp.x;
451ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        coord[1] = lp.y;
452eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung
4538dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        // Since the child hasn't necessarily been laid out, we force the lp to be updated with
454ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        // the correct coordinates (above) and use these to determine the final location
455557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
456ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toX = coord[0];
457ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toY = coord[1];
458ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        if (child instanceof TextView) {
459eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            float childrenScale = parent.getChildrenScale();
460ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            TextView tv = (TextView) child;
461ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen
462eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            // The child may be scaled (always about the center of the view) so to account for it,
463eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            // we have to offset the position by the scaled size.  Once we do that, we can center
464eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            // the drag view about the scaled child view.
465eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            toY += Math.round(((1f - childrenScale) * child.getMeasuredHeight()) / 2 +
466eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung                    scale * childrenScale * tv.getPaddingTop());
467eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            toY -= dragView.getMeasuredHeight() * (1 - scale * childrenScale) / 2;
468ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
469eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung
470eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            scale *= childrenScale;
471ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung        } else if (child instanceof FolderIcon) {
472ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Account for holographic blur padding on the drag view
473d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen            toY -= Workspace.DRAG_BITMAP_PADDING / 2;
474ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Center in the x coordinate about the target's drawable
475ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
476ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        } else {
477ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2;
478ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toX -= (Math.round(scale * (dragView.getMeasuredWidth()
479ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen                    - child.getMeasuredWidth()))) / 2;
480ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        }
481716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
482ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromX = r.left;
483ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromY = r.top;
484716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        child.setVisibility(INVISIBLE);
4858dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Runnable onCompleteRunnable = new Runnable() {
4868dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void run() {
4878dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                child.setVisibility(VISIBLE);
488d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                if (onFinishAnimationRunnable != null) {
489d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                    onFinishAnimationRunnable.run();
490d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                }
4918dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
4928dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        };
493ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, scale, scale,
494d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView);
495557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    }
496557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung
497d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen    public void animateViewIntoPosition(final DragView view, final int fromX, final int fromY,
498ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY,
499ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            float finalScaleX, float finalScaleY, Runnable onCompleteRunnable,
500ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            int animationEndStyle, int duration, View anchorView) {
5018dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Rect from = new Rect(fromX, fromY, fromX +
5028dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                view.getMeasuredWidth(), fromY + view.getMeasuredHeight());
5033e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight());
504ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        animateView(view, from, to, finalAlpha, initScaleX, initScaleY, finalScaleX, finalScaleY, duration,
505ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                null, null, onCompleteRunnable, animationEndStyle, anchorView);
5063e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    }
5073e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
508b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen    /**
509b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * This method animates a view at the end of a drag and drop animation.
510b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *
511b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param view The view to be animated. This view is drawn directly into DragLayer, and so
512b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        doesn't need to be a child of DragLayer.
513b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param from The initial location of the view. Only the left and top parameters are used.
514b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param to The final location of the view. Only the left and top parameters are used. This
515b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        location doesn't account for scaling, and so should be centered about the desired
516b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        final location (including scaling).
517b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalAlpha The final alpha of the view, in case we want it to fade as it animates.
518b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalScale The final scale of the view. The view is scaled about its center.
519b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param duration The duration of the animation.
520b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param motionInterpolator The interpolator to use for the location of the view.
521b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param alphaInterpolator The interpolator to use for the alpha of the view.
522b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param onCompleteRunnable Optional runnable to run on animation completion.
523b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param fadeOut Whether or not to fade out the view once the animation completes. If true,
524b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        the runnable will execute after the view is faded out.
5256441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     * @param anchorView If not null, this represents the view which the animated view stays
5266441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        anchored to in case scrolling is currently taking place. Note: currently this is
5276441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        only used for the X dimension for the case of the workspace.
528b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     */
5297bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateView(final DragView view, final Rect from, final Rect to,
5307bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalAlpha, final float initScaleX, final float initScaleY,
5317bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalScaleX, final float finalScaleY, int duration,
5327bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Interpolator motionInterpolator, final Interpolator alphaInterpolator,
5337bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) {
5347bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
535716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        // Calculate the duration of the animation based on the object's distance
5363e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        final float dist = (float) Math.sqrt(Math.pow(to.left - from.left, 2) +
5373e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                Math.pow(to.top - from.top, 2));
538716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final Resources res = getResources();
539716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
5403e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
5413e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        // If duration < 0, this is a cue to compute the duration based on the distance
5423e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (duration < 0) {
5433e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
5443e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            if (dist < maxDist) {
5458dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist);
5463e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
54761b0c69d3fe331d3de338322396d5de691d58613Winson Chung            duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
548716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        }
549716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
550043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Fall back to cubic ease out interpolator for the animation if none is specified
551043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        TimeInterpolator interpolator = null;
5523e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (alphaInterpolator == null || motionInterpolator == null) {
553043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            interpolator = mCubicEaseOutInterpolator;
5543e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        }
555716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
556043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Animate the view
5577bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        final float initAlpha = view.getAlpha();
558043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float dropViewScale = view.getScaleX();
559043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        AnimatorUpdateListener updateCb = new AnimatorUpdateListener() {
560043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
561716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
562716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
5637bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int width = view.getMeasuredWidth();
5647bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int height = view.getMeasuredHeight();
565716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
5663e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float alphaPercent = alphaInterpolator == null ? percent :
5673e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        alphaInterpolator.getInterpolation(percent);
5683e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float motionPercent = motionInterpolator == null ? percent :
5693e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        motionInterpolator.getInterpolation(percent);
570a1cdab039292f3d809528c0e2e38580b37864d8dWinson Chung
5717bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleX = initScaleX * dropViewScale;
5727bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleY = initScaleY * dropViewScale;
5737bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleX = finalScaleX * percent + initialScaleX * (1 - percent);
5747bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleY = finalScaleY * percent + initialScaleY * (1 - percent);
5757bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float alpha = finalAlpha * alphaPercent + initAlpha * (1 - alphaPercent);
5767bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
5777bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromLeft = from.left + (initialScaleX - 1f) * width / 2;
5787bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromTop = from.top + (initialScaleY - 1f) * height / 2;
5797bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
5807bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent)));
5817bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent)));
5827bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
5837bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int xPos = x - mDropView.getScrollX() + (mAnchorView != null
5847bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                        ? (mAnchorViewInitialScrollX - mAnchorView.getScrollX()) : 0);
5857bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int yPos = y - mDropView.getScrollY();
5867bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
5877bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationX(xPos);
5887bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationY(yPos);
5897bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleX(scaleX);
5907bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleY(scaleY);
5917bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setAlpha(alpha);
592716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            }
593043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
594043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        animateView(view, updateCb, duration, interpolator, onCompleteRunnable, animationEndStyle,
595043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                anchorView);
596043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
597043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
598043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    public void animateView(final DragView view, AnimatorUpdateListener updateCb, int duration,
599043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            TimeInterpolator interpolator, final Runnable onCompleteRunnable,
600043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            final int animationEndStyle, View anchorView) {
601043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Clean up the previous animations
602043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mDropAnim != null) mDropAnim.cancel();
603043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFadeOutAnim != null) mFadeOutAnim.cancel();
604043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
605043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Show the drop view if it was previously hidden
606043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView = view;
607043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView.cancelAnimation();
608043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView.resetLayoutParams();
609043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
610043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Set the anchor view if the page is scrolling
611043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (anchorView != null) {
612043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mAnchorViewInitialScrollX = anchorView.getScrollX();
613043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
614043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mAnchorView = anchorView;
615043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
616043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Create and start the animation
617043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim = new ValueAnimator();
618043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setInterpolator(interpolator);
619043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setDuration(duration);
620043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setFloatValues(0f, 1f);
621043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.addUpdateListener(updateCb);
6223e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mDropAnim.addListener(new AnimatorListenerAdapter() {
6233e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            public void onAnimationEnd(Animator animation) {
6248dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                if (onCompleteRunnable != null) {
6258dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    onCompleteRunnable.run();
6268dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                }
627ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                switch (animationEndStyle) {
628ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_DISAPPEAR:
629ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    clearAnimatedView();
630ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
631ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_FADE_OUT:
6328dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    fadeOutDragView();
633ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
634ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_REMAIN_VISIBLE:
635ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
6363e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                }
6373e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
6383e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        });
639716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mDropAnim.start();
640716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
641716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
642ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public void clearAnimatedView() {
6437bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropAnim != null) {
6447bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            mDropAnim.cancel();
6457bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
6467bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropView != null) {
647043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mDragController.onDeferredEndDrag(mDropView);
6487bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
649ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        mDropView = null;
650ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        invalidate();
651ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
652ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
653ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public View getAnimatedView() {
654ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        return mDropView;
655ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
656ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
6578dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private void fadeOutDragView() {
6588dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim = new ValueAnimator();
6598dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.setDuration(150);
6608dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.setFloatValues(0f, 1f);
6618dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.removeAllUpdateListeners();
6628dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.addUpdateListener(new AnimatorUpdateListener() {
6638dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
6648dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
6657bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
6667bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float alpha = 1 - percent;
6677bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setAlpha(alpha);
6688dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
6698dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        });
6708dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.addListener(new AnimatorListenerAdapter() {
6718dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void onAnimationEnd(Animator animation) {
6727bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                if (mDropView != null) {
673043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mDragController.onDeferredEndDrag(mDropView);
6747bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                }
6758dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                mDropView = null;
676ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                invalidate();
6778dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
6788dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        });
6798dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.start();
6808dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    }
6818dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
682716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    @Override
6838b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewAdded(View parent, View child) {
68421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
68521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
68621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
68721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
6888b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewRemoved(View parent, View child) {
68921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
69021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
69121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
69221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    private void updateChildIndices() {
69321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        if (mLauncher != null) {
69421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            mWorkspaceIndex = indexOfChild(mLauncher.getWorkspace());
695ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen            mQsbIndex = indexOfChild(mLauncher.getSearchBar());
69621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
69721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
69821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
69921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
70021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    protected int getChildDrawingOrder(int childCount, int i) {
701e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung        // We don't want to prioritize the workspace drawing on top of the other children in
702e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung        // landscape for the overscroll event.
703e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung        if (LauncherApplication.isScreenLandscape(getContext())) {
704e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung            return super.getChildDrawingOrder(childCount, i);
705e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung        }
706e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung
707ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        if (mWorkspaceIndex == -1 || mQsbIndex == -1 ||
70821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen                mLauncher.getWorkspace().isDrawingBackgroundGradient()) {
70921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
71021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
71121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
71221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // This ensures that the workspace is drawn above the hotseat and qsb,
71321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // except when the workspace is drawing a background gradient, in which
71421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // case we want the workspace to stay behind these elements.
715ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        if (i == mQsbIndex) {
71621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return mWorkspaceIndex;
71721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        } else if (i == mWorkspaceIndex) {
718ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen            return mQsbIndex;
71921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        } else {
72021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
72121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
72221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
72331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
724