DragLayer.java revision 043f2af567178b82b0b41f12d379e7dd12da2936
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;
26716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.graphics.Canvas;
27043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.graphics.Paint;
28043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.graphics.PointF;
296788269814a678af976dfc7d6135993e172ce586Adam Cohenimport android.graphics.Rect;
3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.KeyEvent;
320e26059548e429e5d1c973bebe4c561bead2926fMichael Jurkaimport android.view.MotionEvent;
33ea3763c2672f77539538af8cdd395ad97058eaabRomain Guyimport android.view.View;
3476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.ViewParent;
353371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityEvent;
363371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityManager;
37043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.view.animation.AnimationUtils;
38716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.view.animation.DecelerateInterpolator;
393e8f811f31a2275e778244427271f77f4116c08bAdam Cohenimport android.view.animation.Interpolator;
4031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.FrameLayout;
41ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohenimport android.widget.TextView;
4231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
43716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport com.android.launcher.R;
44716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
451d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohenimport java.util.ArrayList;
466788269814a678af976dfc7d6135993e172ce586Adam Cohen
4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
480e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * A ViewGroup that coordinates dragging across its descendants
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
5000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratopublic class DragLayer extends FrameLayout {
51120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    private DragController mDragController;
52120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    private int[] mTmpXY = new int[2];
5331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
54716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private int mXDown, mYDown;
55716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private Launcher mLauncher;
56716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
576788269814a678af976dfc7d6135993e172ce586Adam Cohen    // Variables relating to resizing widgets
586788269814a678af976dfc7d6135993e172ce586Adam Cohen    private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
596788269814a678af976dfc7d6135993e172ce586Adam Cohen            new ArrayList<AppWidgetResizeFrame>();
606788269814a678af976dfc7d6135993e172ce586Adam Cohen    private AppWidgetResizeFrame mCurrentResizeFrame;
61716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
62716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    // Variables relating to animation of views after drop
63716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private ValueAnimator mDropAnim = null;
648dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private ValueAnimator mFadeOutAnim = null;
658dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
667bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    private DragView mDropView = null;
676441de0ec2a71862798dd51180d0811b42edd514Adam Cohen    private int mAnchorViewInitialScrollX = 0;
686441de0ec2a71862798dd51180d0811b42edd514Adam Cohen    private View mAnchorView = null;
698dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
703371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean mHoverPointClosesFolder = false;
713371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private Rect mHitRect = new Rect();
7221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    private int mWorkspaceIndex = -1;
73ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen    private int mQsbIndex = -1;
74ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_DISAPPEAR = 0;
75ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_FADE_OUT = 1;
76ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
776788269814a678af976dfc7d6135993e172ce586Adam Cohen
7831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
7931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to create a new DragLayer from XML.
8031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
820e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
8331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
8431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public DragLayer(Context context, AttributeSet attrs) {
8531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs);
86be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung
87be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        // Disable multitouch across the workspace/all apps/customize tray
88be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        setMotionEventSplittingEnabled(false);
8921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        setChildrenDrawingOrderEnabled(true);
9031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
9131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
924c98d9235d164680186180974719f551cf935d08Winson Chung    public void setup(Launcher launcher, DragController controller) {
934c98d9235d164680186180974719f551cf935d08Winson Chung        mLauncher = launcher;
9400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = controller;
9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
9676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
9731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
9831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean dispatchKeyEvent(KeyEvent event) {
9900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1023371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
1033371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect);
1043371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
1053371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return true;
1063371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
1073371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
1083371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1093371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
1103371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
1113371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        getDescendantRectRelativeToSelf(folder, mHitRect);
1123371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
1133371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return true;
1143371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
1153371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
1163371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1173371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
11876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
1196788269814a678af976dfc7d6135993e172ce586Adam Cohen        Rect hitRect = new Rect();
1206788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
1216788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
1226788269814a678af976dfc7d6135993e172ce586Adam Cohen
1236788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (AppWidgetResizeFrame child: mResizeFrames) {
1246788269814a678af976dfc7d6135993e172ce586Adam Cohen            child.getHitRect(hitRect);
1256788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (hitRect.contains(x, y)) {
1266788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
1276788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = child;
1286788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mXDown = x;
1296788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mYDown = y;
1306788269814a678af976dfc7d6135993e172ce586Adam Cohen                    requestDisallowInterceptTouchEvent(true);
1316788269814a678af976dfc7d6135993e172ce586Adam Cohen                    return true;
1326788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
1336788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
1346788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
13576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
1361d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
1377d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung        if (currentFolder != null && !mLauncher.isFolderClingVisible() && intercept) {
1381d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen            if (currentFolder.isEditingName()) {
1393371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                if (!isEventOverFolderTextRegion(currentFolder, ev)) {
1401d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen                    currentFolder.dismissEditingName();
14176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                    return true;
1422801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                }
1432801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            }
14476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
1451d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen            getDescendantRectRelativeToSelf(currentFolder, hitRect);
1463371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            if (!isEventOverFolder(currentFolder, ev)) {
14776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                mLauncher.closeFolder();
14876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                return true;
14976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            }
1502801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
1516788269814a678af976dfc7d6135993e172ce586Adam Cohen        return false;
1526788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
1536788269814a678af976dfc7d6135993e172ce586Adam Cohen
15431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
15531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onInterceptTouchEvent(MotionEvent ev) {
1566788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
15776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            if (handleTouchDown(ev, true)) {
1586788269814a678af976dfc7d6135993e172ce586Adam Cohen                return true;
159d1837cc69eb222371afdd30890f7215d117510f2Patrick Dubroy            }
1601b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen        }
1616788269814a678af976dfc7d6135993e172ce586Adam Cohen        clearAllResizeFrames();
1624db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato        return mDragController.onInterceptTouchEvent(ev);
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
16431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
1663371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onInterceptHoverEvent(MotionEvent ev) {
1673371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
1683371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (currentFolder == null) {
1693371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return false;
1703371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        } else {
1713371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            if (AccessibilityManager.getInstance(mContext).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) {
2043371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
2053371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close;
2063371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            AccessibilityEvent event = AccessibilityEvent.obtain(
2073371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    AccessibilityEvent.TYPE_VIEW_FOCUSED);
2083371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            onInitializeAccessibilityEvent(event);
2093371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            event.getText().add(mContext.getString(stringId));
2103371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            AccessibilityManager.getInstance(mContext).sendAccessibilityEvent(event);
2113371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
2123371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2133371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2143371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
2153371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onHoverEvent(MotionEvent ev) {
2163371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // If we've received this, we've already done the necessary handling
2173371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // in onInterceptHoverEvent. Return true to consume the event.
2183371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
2193371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2203371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2213371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
22231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
2236788269814a678af976dfc7d6135993e172ce586Adam Cohen        boolean handled = false;
2246788269814a678af976dfc7d6135993e172ce586Adam Cohen        int action = ev.getAction();
2256788269814a678af976dfc7d6135993e172ce586Adam Cohen
2266788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
2276788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
2286788269814a678af976dfc7d6135993e172ce586Adam Cohen
2296788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
2306788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
23176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                if (handleTouchDown(ev, false)) {
2326788269814a678af976dfc7d6135993e172ce586Adam Cohen                    return true;
2336788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
2346788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
2356788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
2366788269814a678af976dfc7d6135993e172ce586Adam Cohen
2376788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mCurrentResizeFrame != null) {
2386788269814a678af976dfc7d6135993e172ce586Adam Cohen            handled = true;
2396788269814a678af976dfc7d6135993e172ce586Adam Cohen            switch (action) {
2406788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_MOVE:
2416788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
2426788269814a678af976dfc7d6135993e172ce586Adam Cohen                    break;
2436788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_CANCEL:
2446788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_UP:
2456788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame.commitResizeForDelta(x - mXDown, y - mYDown);
2466788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = null;
2476788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
2486788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
2496788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (handled) return true;
2504db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato        return mDragController.onTouchEvent(ev);
25191a9c9636f10f1e12cd1f660b2e330634fbdc7dcRomain Guy    }
252ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
25335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
25435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Determine the rect of the descendant in this DragLayer's coordinates
25535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
25635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant whose coordinates we want to find.
25735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param r The rect into which to place the results.
25835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer.
25935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
260ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen    public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
261716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[0] = 0;
262716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[1] = 0;
263ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
2648dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        r.set(mTmpXY[0], mTmpXY[1],
2658dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                mTmpXY[0] + descendant.getWidth(), mTmpXY[1] + descendant.getHeight());
266ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        return scale;
267716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
26876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
26935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    public void getLocationInDragLayer(View child, int[] loc) {
27035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[0] = 0;
27135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[1] = 0;
27235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        getDescendantCoordRelativeToSelf(child, loc);
27335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    }
27435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen
27535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
27635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's
27735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * coordinates.
27835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
27935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant to which the passed coordinate is relative.
28035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param coord The coordinate that we want mapped.
28135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer.
28235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
283b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
284557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float scale = 1.0f;
285557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float[] pt = {coord[0], coord[1]};
286557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        descendant.getMatrix().mapPoints(pt);
287557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        scale *= descendant.getScaleX();
288557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        pt[0] += descendant.getLeft();
289557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        pt[1] += descendant.getTop();
29076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        ViewParent viewParent = descendant.getParent();
29176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        while (viewParent instanceof View && viewParent != this) {
29276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            final View view = (View)viewParent;
293557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            view.getMatrix().mapPoints(pt);
294557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            scale *= view.getScaleX();
295557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            pt[0] += view.getLeft() - view.getScrollX();
296557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            pt[1] += view.getTop() - view.getScrollY();
29776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            viewParent = view.getParent();
29876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        }
299fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        coord[0] = (int) Math.round(pt[0]);
300fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        coord[1] = (int) Math.round(pt[1]);
301557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        return scale;
30276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
30376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
3043e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    public void getViewRectRelativeToSelf(View v, Rect r) {
3053e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int[] loc = new int[2];
3068dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        getLocationInWindow(loc);
3073e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int x = loc[0];
3083e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int y = loc[1];
309716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
3108dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        v.getLocationInWindow(loc);
3113e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vX = loc[0];
3123e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vY = loc[1];
313716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
3143e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int left = vX - x;
3153e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int top = vY - y;
3163e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
317716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
318716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
319ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    @Override
320ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    public boolean dispatchUnhandledMove(View focused, int direction) {
321ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        return mDragController.dispatchUnhandledMove(focused, direction);
322ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
323120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen
3246788269814a678af976dfc7d6135993e172ce586Adam Cohen    public static class LayoutParams extends FrameLayout.LayoutParams {
3256788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int x, y;
3266788269814a678af976dfc7d6135993e172ce586Adam Cohen        public boolean customPosition = false;
3276788269814a678af976dfc7d6135993e172ce586Adam Cohen
3286788269814a678af976dfc7d6135993e172ce586Adam Cohen        /**
3296788269814a678af976dfc7d6135993e172ce586Adam Cohen         * {@inheritDoc}
3306788269814a678af976dfc7d6135993e172ce586Adam Cohen         */
3316788269814a678af976dfc7d6135993e172ce586Adam Cohen        public LayoutParams(int width, int height) {
3326788269814a678af976dfc7d6135993e172ce586Adam Cohen            super(width, height);
3336788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3346788269814a678af976dfc7d6135993e172ce586Adam Cohen
3356788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setWidth(int width) {
3366788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.width = width;
3376788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3386788269814a678af976dfc7d6135993e172ce586Adam Cohen
3396788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getWidth() {
3406788269814a678af976dfc7d6135993e172ce586Adam Cohen            return width;
3416788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3426788269814a678af976dfc7d6135993e172ce586Adam Cohen
3436788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setHeight(int height) {
3446788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.height = height;
3456788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3466788269814a678af976dfc7d6135993e172ce586Adam Cohen
3476788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getHeight() {
3486788269814a678af976dfc7d6135993e172ce586Adam Cohen            return height;
3496788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3506788269814a678af976dfc7d6135993e172ce586Adam Cohen
3516788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setX(int x) {
3526788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.x = x;
3536788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3546788269814a678af976dfc7d6135993e172ce586Adam Cohen
3556788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getX() {
3566788269814a678af976dfc7d6135993e172ce586Adam Cohen            return x;
3576788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3586788269814a678af976dfc7d6135993e172ce586Adam Cohen
3596788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setY(int y) {
3606788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.y = y;
3616788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3626788269814a678af976dfc7d6135993e172ce586Adam Cohen
3636788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getY() {
3646788269814a678af976dfc7d6135993e172ce586Adam Cohen            return y;
3656788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3666788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
3676788269814a678af976dfc7d6135993e172ce586Adam Cohen
3686788269814a678af976dfc7d6135993e172ce586Adam Cohen    protected void onLayout(boolean changed, int l, int t, int r, int b) {
3696788269814a678af976dfc7d6135993e172ce586Adam Cohen        super.onLayout(changed, l, t, r, b);
3706788269814a678af976dfc7d6135993e172ce586Adam Cohen        int count = getChildCount();
3716788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (int i = 0; i < count; i++) {
3726788269814a678af976dfc7d6135993e172ce586Adam Cohen            View child = getChildAt(i);
3736788269814a678af976dfc7d6135993e172ce586Adam Cohen            final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
3746788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (flp instanceof LayoutParams) {
3756788269814a678af976dfc7d6135993e172ce586Adam Cohen                final LayoutParams lp = (LayoutParams) flp;
3766788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (lp.customPosition) {
3776788269814a678af976dfc7d6135993e172ce586Adam Cohen                    child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
3786788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
3796788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
3806788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3816788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
3826788269814a678af976dfc7d6135993e172ce586Adam Cohen
3836788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void clearAllResizeFrames() {
3846788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mResizeFrames.size() > 0) {
3856788269814a678af976dfc7d6135993e172ce586Adam Cohen            for (AppWidgetResizeFrame frame: mResizeFrames) {
3866788269814a678af976dfc7d6135993e172ce586Adam Cohen                removeView(frame);
3876788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
3886788269814a678af976dfc7d6135993e172ce586Adam Cohen            mResizeFrames.clear();
3896788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3906788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
3916788269814a678af976dfc7d6135993e172ce586Adam Cohen
3926788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean hasResizeFrames() {
3936788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mResizeFrames.size() > 0;
3946788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
3956788269814a678af976dfc7d6135993e172ce586Adam Cohen
3966788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean isWidgetBeingResized() {
3976788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mCurrentResizeFrame != null;
3986788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
3996788269814a678af976dfc7d6135993e172ce586Adam Cohen
4006788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
4016788269814a678af976dfc7d6135993e172ce586Adam Cohen            CellLayout cellLayout) {
4026788269814a678af976dfc7d6135993e172ce586Adam Cohen        AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
4036788269814a678af976dfc7d6135993e172ce586Adam Cohen                itemInfo, widget, cellLayout, this);
4046788269814a678af976dfc7d6135993e172ce586Adam Cohen
4056788269814a678af976dfc7d6135993e172ce586Adam Cohen        LayoutParams lp = new LayoutParams(-1, -1);
4066788269814a678af976dfc7d6135993e172ce586Adam Cohen        lp.customPosition = true;
4076788269814a678af976dfc7d6135993e172ce586Adam Cohen
4086788269814a678af976dfc7d6135993e172ce586Adam Cohen        addView(resizeFrame, lp);
4096788269814a678af976dfc7d6135993e172ce586Adam Cohen        mResizeFrames.add(resizeFrame);
4106788269814a678af976dfc7d6135993e172ce586Adam Cohen
4116788269814a678af976dfc7d6135993e172ce586Adam Cohen        resizeFrame.snapToWidget(false);
4126788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
413716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
414716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    public void animateViewIntoPosition(DragView dragView, final View child) {
415557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        animateViewIntoPosition(dragView, child, null);
416557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    }
417ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen
4187bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
4197bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
4207bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            int duration) {
421b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        Rect r = new Rect();
422b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        getViewRectRelativeToSelf(dragView, r);
423b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromX = r.left;
424b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromY = r.top;
425b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen
4267bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], alpha, 1, 1, scaleX, scaleY,
427ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                onFinishRunnable, animationEndStyle, duration, null);
428ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
429ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
430557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    public void animateViewIntoPosition(DragView dragView, final View child,
431557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            final Runnable onFinishAnimationRunnable) {
4326441de0ec2a71862798dd51180d0811b42edd514Adam Cohen        animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, null);
433ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    }
434ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen
435ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    public void animateViewIntoPosition(DragView dragView, final View child, int duration,
4366441de0ec2a71862798dd51180d0811b42edd514Adam Cohen            final Runnable onFinishAnimationRunnable, View anchorView) {
437eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung        CellLayoutChildren parentChildren = (CellLayoutChildren) child.getParent();
438eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung        CellLayout parent = (CellLayout) (CellLayout) parentChildren.getParent();
439716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        CellLayout.LayoutParams lp =  (CellLayout.LayoutParams) child.getLayoutParams();
440eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung        parentChildren.measureChild(child);
441716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4423e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect r = new Rect();
4433e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        getViewRectRelativeToSelf(dragView, r);
444716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
445716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        int coord[] = new int[2];
446ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        coord[0] = lp.x;
447ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        coord[1] = lp.y;
448eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung
4498dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        // Since the child hasn't necessarily been laid out, we force the lp to be updated with
450ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        // the correct coordinates (above) and use these to determine the final location
451557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
452ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toX = coord[0];
453ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toY = coord[1];
454ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        if (child instanceof TextView) {
455eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            float childrenScale = parent.getChildrenScale();
456ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            TextView tv = (TextView) child;
457ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen
458eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            // The child may be scaled (always about the center of the view) so to account for it,
459eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            // we have to offset the position by the scaled size.  Once we do that, we can center
460eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            // the drag view about the scaled child view.
461eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            toY += Math.round(((1f - childrenScale) * child.getMeasuredHeight()) / 2 +
462eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung                    scale * childrenScale * tv.getPaddingTop());
463eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            toY -= dragView.getMeasuredHeight() * (1 - scale * childrenScale) / 2;
464ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
465eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung
466eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung            scale *= childrenScale;
467ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung        } else if (child instanceof FolderIcon) {
468ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Account for holographic blur padding on the drag view
469d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen            toY -= Workspace.DRAG_BITMAP_PADDING / 2;
470ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Center in the x coordinate about the target's drawable
471ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
472ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        } else {
473ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2;
474ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toX -= (Math.round(scale * (dragView.getMeasuredWidth()
475ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen                    - child.getMeasuredWidth()))) / 2;
476ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        }
477716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
478ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromX = r.left;
479ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromY = r.top;
480716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        child.setVisibility(INVISIBLE);
4818dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Runnable onCompleteRunnable = new Runnable() {
4828dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void run() {
4838dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                child.setVisibility(VISIBLE);
484d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                if (onFinishAnimationRunnable != null) {
485d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                    onFinishAnimationRunnable.run();
486d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                }
4878dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
4888dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        };
489ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, scale, scale,
490d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView);
491557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    }
492557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung
493d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen    public void animateViewIntoPosition(final DragView view, final int fromX, final int fromY,
494ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY,
495ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            float finalScaleX, float finalScaleY, Runnable onCompleteRunnable,
496ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            int animationEndStyle, int duration, View anchorView) {
4978dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Rect from = new Rect(fromX, fromY, fromX +
4988dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                view.getMeasuredWidth(), fromY + view.getMeasuredHeight());
4993e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight());
500ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        animateView(view, from, to, finalAlpha, initScaleX, initScaleY, finalScaleX, finalScaleY, duration,
501ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                null, null, onCompleteRunnable, animationEndStyle, anchorView);
5023e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    }
5033e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
504b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen    /**
505b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * This method animates a view at the end of a drag and drop animation.
506b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *
507b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param view The view to be animated. This view is drawn directly into DragLayer, and so
508b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        doesn't need to be a child of DragLayer.
509b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param from The initial location of the view. Only the left and top parameters are used.
510b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param to The final location of the view. Only the left and top parameters are used. This
511b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        location doesn't account for scaling, and so should be centered about the desired
512b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        final location (including scaling).
513b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalAlpha The final alpha of the view, in case we want it to fade as it animates.
514b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalScale The final scale of the view. The view is scaled about its center.
515b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param duration The duration of the animation.
516b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param motionInterpolator The interpolator to use for the location of the view.
517b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param alphaInterpolator The interpolator to use for the alpha of the view.
518b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param onCompleteRunnable Optional runnable to run on animation completion.
519b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param fadeOut Whether or not to fade out the view once the animation completes. If true,
520b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        the runnable will execute after the view is faded out.
5216441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     * @param anchorView If not null, this represents the view which the animated view stays
5226441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        anchored to in case scrolling is currently taking place. Note: currently this is
5236441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        only used for the X dimension for the case of the workspace.
524b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     */
5257bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateView(final DragView view, final Rect from, final Rect to,
5267bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalAlpha, final float initScaleX, final float initScaleY,
5277bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalScaleX, final float finalScaleY, int duration,
5287bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Interpolator motionInterpolator, final Interpolator alphaInterpolator,
5297bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) {
5307bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
531716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        // Calculate the duration of the animation based on the object's distance
5323e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        final float dist = (float) Math.sqrt(Math.pow(to.left - from.left, 2) +
5333e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                Math.pow(to.top - from.top, 2));
534716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final Resources res = getResources();
535716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
5363e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
5373e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        // If duration < 0, this is a cue to compute the duration based on the distance
5383e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (duration < 0) {
5393e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
5403e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            if (dist < maxDist) {
5418dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist);
5423e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
54361b0c69d3fe331d3de338322396d5de691d58613Winson Chung            duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
544716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        }
545716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
546043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Fall back to cubic ease out interpolator for the animation if none is specified
547043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        TimeInterpolator interpolator = null;
5483e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (alphaInterpolator == null || motionInterpolator == null) {
549043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            interpolator = mCubicEaseOutInterpolator;
5503e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        }
551716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
552043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Animate the view
5537bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        final float initAlpha = view.getAlpha();
554043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float dropViewScale = view.getScaleX();
555043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        AnimatorUpdateListener updateCb = new AnimatorUpdateListener() {
556043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
557716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
558716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
5597bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int width = view.getMeasuredWidth();
5607bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int height = view.getMeasuredHeight();
561716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
5623e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float alphaPercent = alphaInterpolator == null ? percent :
5633e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        alphaInterpolator.getInterpolation(percent);
5643e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float motionPercent = motionInterpolator == null ? percent :
5653e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        motionInterpolator.getInterpolation(percent);
566a1cdab039292f3d809528c0e2e38580b37864d8dWinson Chung
5677bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleX = initScaleX * dropViewScale;
5687bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleY = initScaleY * dropViewScale;
5697bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleX = finalScaleX * percent + initialScaleX * (1 - percent);
5707bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleY = finalScaleY * percent + initialScaleY * (1 - percent);
5717bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float alpha = finalAlpha * alphaPercent + initAlpha * (1 - alphaPercent);
5727bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
5737bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromLeft = from.left + (initialScaleX - 1f) * width / 2;
5747bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromTop = from.top + (initialScaleY - 1f) * height / 2;
5757bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
5767bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent)));
5777bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent)));
5787bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
5797bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int xPos = x - mDropView.getScrollX() + (mAnchorView != null
5807bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                        ? (mAnchorViewInitialScrollX - mAnchorView.getScrollX()) : 0);
5817bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int yPos = y - mDropView.getScrollY();
5827bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
5837bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationX(xPos);
5847bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationY(yPos);
5857bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleX(scaleX);
5867bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleY(scaleY);
5877bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setAlpha(alpha);
588716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            }
589043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
590043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        animateView(view, updateCb, duration, interpolator, onCompleteRunnable, animationEndStyle,
591043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                anchorView);
592043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
593043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
594043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    public void animateView(final DragView view, AnimatorUpdateListener updateCb, int duration,
595043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            TimeInterpolator interpolator, final Runnable onCompleteRunnable,
596043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            final int animationEndStyle, View anchorView) {
597043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Clean up the previous animations
598043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mDropAnim != null) mDropAnim.cancel();
599043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFadeOutAnim != null) mFadeOutAnim.cancel();
600043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
601043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Show the drop view if it was previously hidden
602043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView = view;
603043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView.cancelAnimation();
604043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView.resetLayoutParams();
605043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
606043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Set the anchor view if the page is scrolling
607043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (anchorView != null) {
608043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mAnchorViewInitialScrollX = anchorView.getScrollX();
609043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
610043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mAnchorView = anchorView;
611043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
612043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Create and start the animation
613043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim = new ValueAnimator();
614043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setInterpolator(interpolator);
615043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setDuration(duration);
616043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setFloatValues(0f, 1f);
617043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.addUpdateListener(updateCb);
6183e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mDropAnim.addListener(new AnimatorListenerAdapter() {
6193e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            public void onAnimationEnd(Animator animation) {
6208dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                if (onCompleteRunnable != null) {
6218dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    onCompleteRunnable.run();
6228dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                }
623ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                switch (animationEndStyle) {
624ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_DISAPPEAR:
625ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    clearAnimatedView();
626ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
627ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_FADE_OUT:
6288dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    fadeOutDragView();
629ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
630ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_REMAIN_VISIBLE:
631ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
6323e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                }
6333e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
6343e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        });
635716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mDropAnim.start();
636716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
637716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
638ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public void clearAnimatedView() {
6397bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropAnim != null) {
6407bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            mDropAnim.cancel();
6417bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
6427bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropView != null) {
643043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mDragController.onDeferredEndDrag(mDropView);
6447bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
645ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        mDropView = null;
646ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        invalidate();
647ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
648ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
649ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public View getAnimatedView() {
650ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        return mDropView;
651ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
652ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
6538dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private void fadeOutDragView() {
6548dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim = new ValueAnimator();
6558dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.setDuration(150);
6568dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.setFloatValues(0f, 1f);
6578dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.removeAllUpdateListeners();
6588dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.addUpdateListener(new AnimatorUpdateListener() {
6598dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
6608dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
6617bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
6627bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float alpha = 1 - percent;
6637bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setAlpha(alpha);
6648dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
6658dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        });
6668dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.addListener(new AnimatorListenerAdapter() {
6678dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void onAnimationEnd(Animator animation) {
6687bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                if (mDropView != null) {
669043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mDragController.onDeferredEndDrag(mDropView);
6707bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                }
6718dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                mDropView = null;
672ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                invalidate();
6738dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
6748dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        });
6758dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.start();
6768dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    }
6778dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
678716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    @Override
67921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    protected void onViewAdded(View child) {
68021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        super.onViewAdded(child);
68121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
68221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
68321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
68421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
68521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    protected void onViewRemoved(View child) {
68621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        super.onViewRemoved(child);
68721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
68821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
68921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
69021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    private void updateChildIndices() {
69121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        if (mLauncher != null) {
69221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            mWorkspaceIndex = indexOfChild(mLauncher.getWorkspace());
693ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen            mQsbIndex = indexOfChild(mLauncher.getSearchBar());
69421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
69521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
69621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
69721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
69821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    protected int getChildDrawingOrder(int childCount, int i) {
699e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung        // We don't want to prioritize the workspace drawing on top of the other children in
700e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung        // landscape for the overscroll event.
701e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung        if (LauncherApplication.isScreenLandscape(getContext())) {
702e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung            return super.getChildDrawingOrder(childCount, i);
703e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung        }
704e96e5cb768fcc6f1211c8c31fa2da4dcd4e465ccWinson Chung
705ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        if (mWorkspaceIndex == -1 || mQsbIndex == -1 ||
70621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen                mLauncher.getWorkspace().isDrawingBackgroundGradient()) {
70721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
70821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
70921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
71021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // This ensures that the workspace is drawn above the hotseat and qsb,
71121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // except when the workspace is drawing a background gradient, in which
71221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // case we want the workspace to stay behind these elements.
713ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        if (i == mQsbIndex) {
71421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return mWorkspaceIndex;
71521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        } else if (i == mWorkspaceIndex) {
716ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen            return mQsbIndex;
71721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        } else {
71821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
71921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
72021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
72131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
722