DragLayer.java revision c9ca2980983ab21fc8631c7a65399d6d9c70f39c
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
17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3;
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;
26360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chungimport android.graphics.Canvas;
277d30a37007bac318db1c9af47a9af12d348042a5Adam Cohenimport android.graphics.Matrix;
286788269814a678af976dfc7d6135993e172ce586Adam Cohenimport android.graphics.Rect;
29360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chungimport android.graphics.drawable.Drawable;
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;
348b805b17158886035b38261eb611d8641701ae43Michael Jurkaimport android.view.ViewGroup;
3576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.ViewParent;
363371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityEvent;
373371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityManager;
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
431d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohenimport java.util.ArrayList;
446788269814a678af976dfc7d6135993e172ce586Adam Cohen
4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
460e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * A ViewGroup that coordinates dragging across its descendants
4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
488b805b17158886035b38261eb611d8641701ae43Michael Jurkapublic class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChangeListener {
49120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    private DragController mDragController;
50120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    private int[] mTmpXY = new int[2];
5131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
52716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private int mXDown, mYDown;
53716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private Launcher mLauncher;
54716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
556788269814a678af976dfc7d6135993e172ce586Adam Cohen    // Variables relating to resizing widgets
566788269814a678af976dfc7d6135993e172ce586Adam Cohen    private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
576788269814a678af976dfc7d6135993e172ce586Adam Cohen            new ArrayList<AppWidgetResizeFrame>();
586788269814a678af976dfc7d6135993e172ce586Adam Cohen    private AppWidgetResizeFrame mCurrentResizeFrame;
59716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
60716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    // Variables relating to animation of views after drop
61716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private ValueAnimator mDropAnim = null;
628dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private ValueAnimator mFadeOutAnim = null;
638dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
647bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    private DragView mDropView = null;
656441de0ec2a71862798dd51180d0811b42edd514Adam Cohen    private int mAnchorViewInitialScrollX = 0;
666441de0ec2a71862798dd51180d0811b42edd514Adam Cohen    private View mAnchorView = null;
678dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
683371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean mHoverPointClosesFolder = false;
693371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private Rect mHitRect = new Rect();
7021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    private int mWorkspaceIndex = -1;
71ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen    private int mQsbIndex = -1;
72ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_DISAPPEAR = 0;
73ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_FADE_OUT = 1;
74ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
756788269814a678af976dfc7d6135993e172ce586Adam Cohen
7631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
7731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to create a new DragLayer from XML.
7831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
7931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
800e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
8231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public DragLayer(Context context, AttributeSet attrs) {
8331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs);
84be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung
85be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        // Disable multitouch across the workspace/all apps/customize tray
86be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        setMotionEventSplittingEnabled(false);
8721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        setChildrenDrawingOrderEnabled(true);
888b805b17158886035b38261eb611d8641701ae43Michael Jurka        setOnHierarchyChangeListener(this);
89360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
90360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        mLeftHoverDrawable = getResources().getDrawable(R.drawable.page_hover_left_holo);
91360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        mRightHoverDrawable = getResources().getDrawable(R.drawable.page_hover_right_holo);
9231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
9331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
944c98d9235d164680186180974719f551cf935d08Winson Chung    public void setup(Launcher launcher, DragController controller) {
954c98d9235d164680186180974719f551cf935d08Winson Chung        mLauncher = launcher;
9600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = controller;
9731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
9876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean dispatchKeyEvent(KeyEvent event) {
10100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
10231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1043371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
1053371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect);
1063371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
1073371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return true;
1083371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
1093371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
1103371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1113371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
1123371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
1133371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        getDescendantRectRelativeToSelf(folder, mHitRect);
1143371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
1153371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return true;
1163371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
1173371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
1183371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1193371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
12076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
1216788269814a678af976dfc7d6135993e172ce586Adam Cohen        Rect hitRect = new Rect();
1226788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
1236788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
1246788269814a678af976dfc7d6135993e172ce586Adam Cohen
1256788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (AppWidgetResizeFrame child: mResizeFrames) {
1266788269814a678af976dfc7d6135993e172ce586Adam Cohen            child.getHitRect(hitRect);
1276788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (hitRect.contains(x, y)) {
1286788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
1296788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = child;
1306788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mXDown = x;
1316788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mYDown = y;
1326788269814a678af976dfc7d6135993e172ce586Adam Cohen                    requestDisallowInterceptTouchEvent(true);
1336788269814a678af976dfc7d6135993e172ce586Adam Cohen                    return true;
1346788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
1356788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
1366788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
13776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
1381d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
1397d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung        if (currentFolder != null && !mLauncher.isFolderClingVisible() && intercept) {
1401d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen            if (currentFolder.isEditingName()) {
1413371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                if (!isEventOverFolderTextRegion(currentFolder, ev)) {
1421d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen                    currentFolder.dismissEditingName();
14376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                    return true;
1442801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                }
1452801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            }
14676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
1471d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen            getDescendantRectRelativeToSelf(currentFolder, hitRect);
1483371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            if (!isEventOverFolder(currentFolder, ev)) {
14976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                mLauncher.closeFolder();
15076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                return true;
15176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            }
1522801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
1536788269814a678af976dfc7d6135993e172ce586Adam Cohen        return false;
1546788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
1556788269814a678af976dfc7d6135993e172ce586Adam Cohen
15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
15731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onInterceptTouchEvent(MotionEvent ev) {
1586788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
15976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            if (handleTouchDown(ev, true)) {
1606788269814a678af976dfc7d6135993e172ce586Adam Cohen                return true;
161d1837cc69eb222371afdd30890f7215d117510f2Patrick Dubroy            }
1621b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen        }
1636788269814a678af976dfc7d6135993e172ce586Adam Cohen        clearAllResizeFrames();
1644db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato        return mDragController.onInterceptTouchEvent(ev);
16531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
16631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
1683371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onInterceptHoverEvent(MotionEvent ev) {
169023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka        if (mLauncher == null || mLauncher.getWorkspace() == null) {
170023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka            return false;
171023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka        }
1723371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
1733371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (currentFolder == null) {
1743371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return false;
1753371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        } else {
1768b805b17158886035b38261eb611d8641701ae43Michael Jurka                AccessibilityManager accessibilityManager = (AccessibilityManager)
1778b805b17158886035b38261eb611d8641701ae43Michael Jurka                        getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
1788b805b17158886035b38261eb611d8641701ae43Michael Jurka            if (accessibilityManager.isTouchExplorationEnabled()) {
1793371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                final int action = ev.getAction();
1803371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                boolean isOverFolder;
1813371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                switch (action) {
1823371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_ENTER:
1833371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        isOverFolder = isEventOverFolder(currentFolder, ev);
1843371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        if (!isOverFolder) {
1853371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
1863371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
1873371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
1883371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else if (isOverFolder) {
1893371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = false;
1903371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else {
1913371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
1923371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
1933371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_MOVE:
1943371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        isOverFolder = isEventOverFolder(currentFolder, ev);
1953371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        if (!isOverFolder && !mHoverPointClosesFolder) {
1963371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
1973371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
1983371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
1993371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else if (isOverFolder) {
2003371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = false;
2013371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else {
2023371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
2033371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
2043371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                }
2053371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            }
2063371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
2073371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
2083371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2093371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2103371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private void sendTapOutsideFolderAccessibilityEvent(boolean isEditingName) {
2118b805b17158886035b38261eb611d8641701ae43Michael Jurka        AccessibilityManager accessibilityManager = (AccessibilityManager)
2128b805b17158886035b38261eb611d8641701ae43Michael Jurka                getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
2138b805b17158886035b38261eb611d8641701ae43Michael Jurka        if (accessibilityManager.isEnabled()) {
2143371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close;
2153371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            AccessibilityEvent event = AccessibilityEvent.obtain(
2163371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    AccessibilityEvent.TYPE_VIEW_FOCUSED);
2173371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            onInitializeAccessibilityEvent(event);
2188b805b17158886035b38261eb611d8641701ae43Michael Jurka            event.getText().add(getContext().getString(stringId));
2198b805b17158886035b38261eb611d8641701ae43Michael Jurka            accessibilityManager.sendAccessibilityEvent(event);
2203371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
22183ca480941b3dd635b62347008fc8d7859d82002Winson Chung    }
22283ca480941b3dd635b62347008fc8d7859d82002Winson Chung
22383ca480941b3dd635b62347008fc8d7859d82002Winson Chung    @Override
22483ca480941b3dd635b62347008fc8d7859d82002Winson Chung    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
22583ca480941b3dd635b62347008fc8d7859d82002Winson Chung        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
22683ca480941b3dd635b62347008fc8d7859d82002Winson Chung        if (currentFolder != null) {
22783ca480941b3dd635b62347008fc8d7859d82002Winson Chung            if (child == currentFolder) {
22883ca480941b3dd635b62347008fc8d7859d82002Winson Chung                return super.onRequestSendAccessibilityEvent(child, event);
22983ca480941b3dd635b62347008fc8d7859d82002Winson Chung            }
23083ca480941b3dd635b62347008fc8d7859d82002Winson Chung            // Skip propagating onRequestSendAccessibilityEvent all for other children
23183ca480941b3dd635b62347008fc8d7859d82002Winson Chung            // when a folder is open
23283ca480941b3dd635b62347008fc8d7859d82002Winson Chung            return false;
23383ca480941b3dd635b62347008fc8d7859d82002Winson Chung        }
23483ca480941b3dd635b62347008fc8d7859d82002Winson Chung        return super.onRequestSendAccessibilityEvent(child, event);
23583ca480941b3dd635b62347008fc8d7859d82002Winson Chung    }
23683ca480941b3dd635b62347008fc8d7859d82002Winson Chung
23783ca480941b3dd635b62347008fc8d7859d82002Winson Chung    @Override
23883ca480941b3dd635b62347008fc8d7859d82002Winson Chung    public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
23983ca480941b3dd635b62347008fc8d7859d82002Winson Chung        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
24083ca480941b3dd635b62347008fc8d7859d82002Winson Chung        if (currentFolder != null) {
24183ca480941b3dd635b62347008fc8d7859d82002Winson Chung            // Only add the folder as a child for accessibility when it is open
24283ca480941b3dd635b62347008fc8d7859d82002Winson Chung            childrenForAccessibility.add(currentFolder);
24383ca480941b3dd635b62347008fc8d7859d82002Winson Chung        } else {
24483ca480941b3dd635b62347008fc8d7859d82002Winson Chung            super.addChildrenForAccessibility(childrenForAccessibility);
24583ca480941b3dd635b62347008fc8d7859d82002Winson Chung        }
2463371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2473371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2483371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
2493371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onHoverEvent(MotionEvent ev) {
2503371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // If we've received this, we've already done the necessary handling
2513371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // in onInterceptHoverEvent. Return true to consume the event.
2523371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
2533371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2543371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2553371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
2576788269814a678af976dfc7d6135993e172ce586Adam Cohen        boolean handled = false;
2586788269814a678af976dfc7d6135993e172ce586Adam Cohen        int action = ev.getAction();
2596788269814a678af976dfc7d6135993e172ce586Adam Cohen
2606788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
2616788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
2626788269814a678af976dfc7d6135993e172ce586Adam Cohen
2636788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
2646788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
26576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                if (handleTouchDown(ev, false)) {
2666788269814a678af976dfc7d6135993e172ce586Adam Cohen                    return true;
2676788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
2686788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
2696788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
2706788269814a678af976dfc7d6135993e172ce586Adam Cohen
2716788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mCurrentResizeFrame != null) {
2726788269814a678af976dfc7d6135993e172ce586Adam Cohen            handled = true;
2736788269814a678af976dfc7d6135993e172ce586Adam Cohen            switch (action) {
2746788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_MOVE:
2756788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
2766788269814a678af976dfc7d6135993e172ce586Adam Cohen                    break;
2776788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_CANCEL:
2786788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_UP:
279bebf042666cffe52039b875a549a582abd78a431Adam Cohen                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
280bebf042666cffe52039b875a549a582abd78a431Adam Cohen                    mCurrentResizeFrame.onTouchUp();
2816788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = null;
2826788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
2836788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
2846788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (handled) return true;
2854db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato        return mDragController.onTouchEvent(ev);
28691a9c9636f10f1e12cd1f660b2e330634fbdc7dcRomain Guy    }
287ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
28835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
28935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Determine the rect of the descendant in this DragLayer's coordinates
29035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
29135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant whose coordinates we want to find.
29235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param r The rect into which to place the results.
29335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer.
29435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
295ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen    public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
296716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[0] = 0;
297716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[1] = 0;
298ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
2997d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3008dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        r.set(mTmpXY[0], mTmpXY[1],
3017d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                (int) (mTmpXY[0] + scale * descendant.getMeasuredWidth()),
3027d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                (int) (mTmpXY[1] + scale * descendant.getMeasuredHeight()));
303ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        return scale;
304716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
30576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
306307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen    public float getLocationInDragLayer(View child, int[] loc) {
30735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[0] = 0;
30835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[1] = 0;
309307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        return getDescendantCoordRelativeToSelf(child, loc);
31035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    }
31135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen
3127d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
3137d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        return getDescendantCoordRelativeToSelf(descendant, coord, false);
3147d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    }
3157d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
31635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
31735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's
31835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * coordinates.
31935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
32035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant to which the passed coordinate is relative.
32135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param coord The coordinate that we want mapped.
3227d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     * @param includeRootScroll Whether or not to account for the scroll of the root descendant:
3237d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     *          sometimes this is relevant as in a child's coordinates within the root descendant.
324307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer. Caution
325307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     *         this scale factor is assumed to be equal in X and Y, and so if at any point this
326307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     *         assumption fails, we will need to return a pair of scale factors.
32735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
3287d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord,
3297d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            boolean includeRootScroll) {
330c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung        return DragLayer.getDescendantCoordRelativeToParent(descendant, this,
331c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung                coord, includeRootScroll);
332c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung    }
333c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung
334c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung    public static float getDescendantCoordRelativeToParent(View descendant, View root,
335c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung            int[] coord, boolean includeRootScroll) {
3367d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        ArrayList<View> ancestorChain = new ArrayList<View>();
3377d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3387d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        float[] pt = {coord[0], coord[1]};
3397d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3407d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        View v = descendant;
341c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung        while(v != root && v != null) {
3427d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            ancestorChain.add(v);
3437d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            v = (View) v.getParent();
3447d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        }
345c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung        ancestorChain.add(root);
3467d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
347557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float scale = 1.0f;
3487d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        int count = ancestorChain.size();
3497d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        for (int i = 0; i < count; i++) {
3507d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            View v0 = ancestorChain.get(i);
3517d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            View v1 = i < count -1 ? ancestorChain.get(i + 1) : null;
3527d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3537d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            // For TextViews, scroll has a meaning which relates to the text position
3547d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            // which is very strange... ignore the scroll.
3557d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            if (v0 != descendant || includeRootScroll) {
3567d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                pt[0] -= v0.getScrollX();
3577d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                pt[1] -= v0.getScrollY();
3587d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            }
3597d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3607d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            v0.getMatrix().mapPoints(pt);
3617d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            pt[0] += v0.getLeft();
3627d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            pt[1] += v0.getTop();
3637d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            scale *= v0.getScaleX();
3647d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        }
3657d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3667d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        coord[0] = (int) Math.round(pt[0]);
3677d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        coord[1] = (int) Math.round(pt[1]);
3687d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        return scale;
3697d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    }
3707d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3717d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    /**
3727d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     * Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}.
3737d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     */
3747d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    public float mapCoordInSelfToDescendent(View descendant, int[] coord) {
3757d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        ArrayList<View> ancestorChain = new ArrayList<View>();
3767d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
377557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float[] pt = {coord[0], coord[1]};
3787d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3797d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        View v = descendant;
3807d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        while(v != this) {
3817d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            ancestorChain.add(v);
3827d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            v = (View) v.getParent();
38376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        }
3847d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        ancestorChain.add(this);
3857d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3867d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        float scale = 1.0f;
3877d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        Matrix inverse = new Matrix();
3887d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        int count = ancestorChain.size();
3897d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        for (int i = count - 1; i >= 0; i--) {
3907d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            View ancestor = ancestorChain.get(i);
3917d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            View next = i > 0 ? ancestorChain.get(i-1) : null;
3927d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3937d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            pt[0] += ancestor.getScrollX();
3947d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            pt[1] += ancestor.getScrollY();
3957d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3967d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            if (next != null) {
3977d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                pt[0] -= next.getLeft();
3987d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                pt[1] -= next.getTop();
3997d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                next.getMatrix().invert(inverse);
4007d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                inverse.mapPoints(pt);
4017d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                scale *= next.getScaleX();
4027d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            }
4037d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        }
4047d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
405fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        coord[0] = (int) Math.round(pt[0]);
406fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        coord[1] = (int) Math.round(pt[1]);
407557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        return scale;
40876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
40976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
4103e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    public void getViewRectRelativeToSelf(View v, Rect r) {
4113e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int[] loc = new int[2];
4128dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        getLocationInWindow(loc);
4133e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int x = loc[0];
4143e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int y = loc[1];
415716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4168dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        v.getLocationInWindow(loc);
4173e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vX = loc[0];
4183e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vY = loc[1];
419716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4203e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int left = vX - x;
4213e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int top = vY - y;
4223e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
423716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
424716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
425ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    @Override
426ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    public boolean dispatchUnhandledMove(View focused, int direction) {
427ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        return mDragController.dispatchUnhandledMove(focused, direction);
428ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
429120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen
4306788269814a678af976dfc7d6135993e172ce586Adam Cohen    public static class LayoutParams extends FrameLayout.LayoutParams {
4316788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int x, y;
4326788269814a678af976dfc7d6135993e172ce586Adam Cohen        public boolean customPosition = false;
4336788269814a678af976dfc7d6135993e172ce586Adam Cohen
4346788269814a678af976dfc7d6135993e172ce586Adam Cohen        /**
4356788269814a678af976dfc7d6135993e172ce586Adam Cohen         * {@inheritDoc}
4366788269814a678af976dfc7d6135993e172ce586Adam Cohen         */
4376788269814a678af976dfc7d6135993e172ce586Adam Cohen        public LayoutParams(int width, int height) {
4386788269814a678af976dfc7d6135993e172ce586Adam Cohen            super(width, height);
4396788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4406788269814a678af976dfc7d6135993e172ce586Adam Cohen
4416788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setWidth(int width) {
4426788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.width = width;
4436788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4446788269814a678af976dfc7d6135993e172ce586Adam Cohen
4456788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getWidth() {
4466788269814a678af976dfc7d6135993e172ce586Adam Cohen            return width;
4476788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4486788269814a678af976dfc7d6135993e172ce586Adam Cohen
4496788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setHeight(int height) {
4506788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.height = height;
4516788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4526788269814a678af976dfc7d6135993e172ce586Adam Cohen
4536788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getHeight() {
4546788269814a678af976dfc7d6135993e172ce586Adam Cohen            return height;
4556788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4566788269814a678af976dfc7d6135993e172ce586Adam Cohen
4576788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setX(int x) {
4586788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.x = x;
4596788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4606788269814a678af976dfc7d6135993e172ce586Adam Cohen
4616788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getX() {
4626788269814a678af976dfc7d6135993e172ce586Adam Cohen            return x;
4636788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4646788269814a678af976dfc7d6135993e172ce586Adam Cohen
4656788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setY(int y) {
4666788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.y = y;
4676788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4686788269814a678af976dfc7d6135993e172ce586Adam Cohen
4696788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getY() {
4706788269814a678af976dfc7d6135993e172ce586Adam Cohen            return y;
4716788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4726788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
4736788269814a678af976dfc7d6135993e172ce586Adam Cohen
4746788269814a678af976dfc7d6135993e172ce586Adam Cohen    protected void onLayout(boolean changed, int l, int t, int r, int b) {
4756788269814a678af976dfc7d6135993e172ce586Adam Cohen        super.onLayout(changed, l, t, r, b);
4766788269814a678af976dfc7d6135993e172ce586Adam Cohen        int count = getChildCount();
4776788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (int i = 0; i < count; i++) {
4786788269814a678af976dfc7d6135993e172ce586Adam Cohen            View child = getChildAt(i);
4796788269814a678af976dfc7d6135993e172ce586Adam Cohen            final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
4806788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (flp instanceof LayoutParams) {
4816788269814a678af976dfc7d6135993e172ce586Adam Cohen                final LayoutParams lp = (LayoutParams) flp;
4826788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (lp.customPosition) {
4836788269814a678af976dfc7d6135993e172ce586Adam Cohen                    child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
4846788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
4856788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
4866788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4876788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
4886788269814a678af976dfc7d6135993e172ce586Adam Cohen
4896788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void clearAllResizeFrames() {
4906788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mResizeFrames.size() > 0) {
4916788269814a678af976dfc7d6135993e172ce586Adam Cohen            for (AppWidgetResizeFrame frame: mResizeFrames) {
492bebf042666cffe52039b875a549a582abd78a431Adam Cohen                frame.commitResize();
4936788269814a678af976dfc7d6135993e172ce586Adam Cohen                removeView(frame);
4946788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
4956788269814a678af976dfc7d6135993e172ce586Adam Cohen            mResizeFrames.clear();
4966788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4976788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
4986788269814a678af976dfc7d6135993e172ce586Adam Cohen
4996788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean hasResizeFrames() {
5006788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mResizeFrames.size() > 0;
5016788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5026788269814a678af976dfc7d6135993e172ce586Adam Cohen
5036788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean isWidgetBeingResized() {
5046788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mCurrentResizeFrame != null;
5056788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5066788269814a678af976dfc7d6135993e172ce586Adam Cohen
5076788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
5086788269814a678af976dfc7d6135993e172ce586Adam Cohen            CellLayout cellLayout) {
5096788269814a678af976dfc7d6135993e172ce586Adam Cohen        AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
5103a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka                widget, cellLayout, this);
5116788269814a678af976dfc7d6135993e172ce586Adam Cohen
5126788269814a678af976dfc7d6135993e172ce586Adam Cohen        LayoutParams lp = new LayoutParams(-1, -1);
5136788269814a678af976dfc7d6135993e172ce586Adam Cohen        lp.customPosition = true;
5146788269814a678af976dfc7d6135993e172ce586Adam Cohen
5156788269814a678af976dfc7d6135993e172ce586Adam Cohen        addView(resizeFrame, lp);
5166788269814a678af976dfc7d6135993e172ce586Adam Cohen        mResizeFrames.add(resizeFrame);
5176788269814a678af976dfc7d6135993e172ce586Adam Cohen
5186788269814a678af976dfc7d6135993e172ce586Adam Cohen        resizeFrame.snapToWidget(false);
5196788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
520716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
521716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    public void animateViewIntoPosition(DragView dragView, final View child) {
522557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        animateViewIntoPosition(dragView, child, null);
523557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    }
524ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen
5257bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
5267bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
5277bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            int duration) {
528b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        Rect r = new Rect();
529b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        getViewRectRelativeToSelf(dragView, r);
530b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromX = r.left;
531b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromY = r.top;
532b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen
5337bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], alpha, 1, 1, scaleX, scaleY,
534ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                onFinishRunnable, animationEndStyle, duration, null);
535ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
536ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
537557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    public void animateViewIntoPosition(DragView dragView, final View child,
538557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            final Runnable onFinishAnimationRunnable) {
5396441de0ec2a71862798dd51180d0811b42edd514Adam Cohen        animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, null);
540ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    }
541ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen
542ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    public void animateViewIntoPosition(DragView dragView, final View child, int duration,
5436441de0ec2a71862798dd51180d0811b42edd514Adam Cohen            final Runnable onFinishAnimationRunnable, View anchorView) {
544a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka        ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent();
545716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        CellLayout.LayoutParams lp =  (CellLayout.LayoutParams) child.getLayoutParams();
546eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung        parentChildren.measureChild(child);
547716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
5483e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect r = new Rect();
5493e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        getViewRectRelativeToSelf(dragView, r);
550716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
551716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        int coord[] = new int[2];
552307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        float childScale = child.getScaleX();
553307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        coord[0] = lp.x + (int) (child.getMeasuredWidth() * (1 - childScale) / 2);
554307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        coord[1] = lp.y + (int) (child.getMeasuredHeight() * (1 - childScale) / 2);
555eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung
5568dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        // Since the child hasn't necessarily been laid out, we force the lp to be updated with
557ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        // the correct coordinates (above) and use these to determine the final location
558557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
559307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // We need to account for the scale of the child itself, as the above only accounts for
560307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // for the scale in parents.
561307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        scale *= childScale;
562ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toX = coord[0];
563ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toY = coord[1];
5644497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn        if (child instanceof TextView) {
5654497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            TextView tv = (TextView) child;
5664497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn
5674497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // The child may be scaled (always about the center of the view) so to account for it,
5684497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // we have to offset the position by the scaled size.  Once we do that, we can center
5694497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // the drag view about the scaled child view.
5704497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            toY += Math.round(scale * tv.getPaddingTop());
5714497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            toY -= dragView.getMeasuredHeight() * (1 - scale) / 2;
5724497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
5734497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn        } else if (child instanceof FolderIcon) {
574ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Account for holographic blur padding on the drag view
575307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen            toY -= scale * Workspace.DRAG_BITMAP_PADDING / 2;
576307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen            toY -= (1 - scale) * dragView.getMeasuredHeight() / 2;
577ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Center in the x coordinate about the target's drawable
578ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
579ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        } else {
580ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2;
581ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toX -= (Math.round(scale * (dragView.getMeasuredWidth()
582ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen                    - child.getMeasuredWidth()))) / 2;
583ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        }
584716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
585ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromX = r.left;
586ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromY = r.top;
587716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        child.setVisibility(INVISIBLE);
5888dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Runnable onCompleteRunnable = new Runnable() {
5898dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void run() {
5908dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                child.setVisibility(VISIBLE);
591d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                if (onFinishAnimationRunnable != null) {
592d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                    onFinishAnimationRunnable.run();
593d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                }
5948dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
5958dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        };
596ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, scale, scale,
597d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView);
598557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    }
599557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung
600d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen    public void animateViewIntoPosition(final DragView view, final int fromX, final int fromY,
601ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY,
602ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            float finalScaleX, float finalScaleY, Runnable onCompleteRunnable,
603ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            int animationEndStyle, int duration, View anchorView) {
6048dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Rect from = new Rect(fromX, fromY, fromX +
6058dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                view.getMeasuredWidth(), fromY + view.getMeasuredHeight());
6063e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight());
607ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        animateView(view, from, to, finalAlpha, initScaleX, initScaleY, finalScaleX, finalScaleY, duration,
608ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                null, null, onCompleteRunnable, animationEndStyle, anchorView);
6093e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    }
6103e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
611b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen    /**
612b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * This method animates a view at the end of a drag and drop animation.
613b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *
614b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param view The view to be animated. This view is drawn directly into DragLayer, and so
615b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        doesn't need to be a child of DragLayer.
616b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param from The initial location of the view. Only the left and top parameters are used.
617b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param to The final location of the view. Only the left and top parameters are used. This
618b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        location doesn't account for scaling, and so should be centered about the desired
619b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        final location (including scaling).
620b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalAlpha The final alpha of the view, in case we want it to fade as it animates.
621b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalScale The final scale of the view. The view is scaled about its center.
622b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param duration The duration of the animation.
623b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param motionInterpolator The interpolator to use for the location of the view.
624b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param alphaInterpolator The interpolator to use for the alpha of the view.
625b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param onCompleteRunnable Optional runnable to run on animation completion.
626b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param fadeOut Whether or not to fade out the view once the animation completes. If true,
627b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        the runnable will execute after the view is faded out.
6286441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     * @param anchorView If not null, this represents the view which the animated view stays
6296441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        anchored to in case scrolling is currently taking place. Note: currently this is
6306441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        only used for the X dimension for the case of the workspace.
631b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     */
6327bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateView(final DragView view, final Rect from, final Rect to,
6337bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalAlpha, final float initScaleX, final float initScaleY,
6347bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalScaleX, final float finalScaleY, int duration,
6357bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Interpolator motionInterpolator, final Interpolator alphaInterpolator,
6367bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) {
6377bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
638716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        // Calculate the duration of the animation based on the object's distance
6393e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        final float dist = (float) Math.sqrt(Math.pow(to.left - from.left, 2) +
6403e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                Math.pow(to.top - from.top, 2));
641716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final Resources res = getResources();
642716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
6433e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
6443e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        // If duration < 0, this is a cue to compute the duration based on the distance
6453e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (duration < 0) {
6463e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
6473e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            if (dist < maxDist) {
6488dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist);
6493e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
65061b0c69d3fe331d3de338322396d5de691d58613Winson Chung            duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
651716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        }
652716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
653043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Fall back to cubic ease out interpolator for the animation if none is specified
654043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        TimeInterpolator interpolator = null;
6553e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (alphaInterpolator == null || motionInterpolator == null) {
656043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            interpolator = mCubicEaseOutInterpolator;
6573e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        }
658716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
659043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Animate the view
6607bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        final float initAlpha = view.getAlpha();
661043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float dropViewScale = view.getScaleX();
662043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        AnimatorUpdateListener updateCb = new AnimatorUpdateListener() {
663043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
664716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
665716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
6667bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int width = view.getMeasuredWidth();
6677bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int height = view.getMeasuredHeight();
668716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
6693e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float alphaPercent = alphaInterpolator == null ? percent :
6703e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        alphaInterpolator.getInterpolation(percent);
6713e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float motionPercent = motionInterpolator == null ? percent :
6723e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        motionInterpolator.getInterpolation(percent);
673a1cdab039292f3d809528c0e2e38580b37864d8dWinson Chung
6747bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleX = initScaleX * dropViewScale;
6757bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleY = initScaleY * dropViewScale;
6767bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleX = finalScaleX * percent + initialScaleX * (1 - percent);
6777bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleY = finalScaleY * percent + initialScaleY * (1 - percent);
6787bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float alpha = finalAlpha * alphaPercent + initAlpha * (1 - alphaPercent);
6797bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
6807bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromLeft = from.left + (initialScaleX - 1f) * width / 2;
6817bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromTop = from.top + (initialScaleY - 1f) * height / 2;
6827bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
6837bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent)));
6847bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent)));
6857bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
6867bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int xPos = x - mDropView.getScrollX() + (mAnchorView != null
6877bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                        ? (mAnchorViewInitialScrollX - mAnchorView.getScrollX()) : 0);
6887bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int yPos = y - mDropView.getScrollY();
6897bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
6907bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationX(xPos);
6917bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationY(yPos);
6927bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleX(scaleX);
6937bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleY(scaleY);
6947bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setAlpha(alpha);
695716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            }
696043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
697043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        animateView(view, updateCb, duration, interpolator, onCompleteRunnable, animationEndStyle,
698043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                anchorView);
699043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
700043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
701043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    public void animateView(final DragView view, AnimatorUpdateListener updateCb, int duration,
702043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            TimeInterpolator interpolator, final Runnable onCompleteRunnable,
703043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            final int animationEndStyle, View anchorView) {
704043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Clean up the previous animations
705043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mDropAnim != null) mDropAnim.cancel();
706043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFadeOutAnim != null) mFadeOutAnim.cancel();
707043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
708043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Show the drop view if it was previously hidden
709043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView = view;
710043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView.cancelAnimation();
711043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView.resetLayoutParams();
712043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
713043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Set the anchor view if the page is scrolling
714043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (anchorView != null) {
715043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mAnchorViewInitialScrollX = anchorView.getScrollX();
716043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
717043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mAnchorView = anchorView;
718043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
719043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Create and start the animation
720043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim = new ValueAnimator();
721043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setInterpolator(interpolator);
722043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setDuration(duration);
723043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setFloatValues(0f, 1f);
724043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.addUpdateListener(updateCb);
7253e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mDropAnim.addListener(new AnimatorListenerAdapter() {
7263e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            public void onAnimationEnd(Animator animation) {
7278dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                if (onCompleteRunnable != null) {
7288dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    onCompleteRunnable.run();
7298dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                }
730ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                switch (animationEndStyle) {
731ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_DISAPPEAR:
732ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    clearAnimatedView();
733ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
734ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_FADE_OUT:
7358dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    fadeOutDragView();
736ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
737ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_REMAIN_VISIBLE:
738ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
7393e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                }
7403e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
7413e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        });
742716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mDropAnim.start();
743716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
744716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
745ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public void clearAnimatedView() {
7467bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropAnim != null) {
7477bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            mDropAnim.cancel();
7487bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
7497bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropView != null) {
750043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mDragController.onDeferredEndDrag(mDropView);
7517bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
752ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        mDropView = null;
753ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        invalidate();
754ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
755ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
756ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public View getAnimatedView() {
757ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        return mDropView;
758ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
759ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
7608dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private void fadeOutDragView() {
7618dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim = new ValueAnimator();
7628dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.setDuration(150);
7638dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.setFloatValues(0f, 1f);
7648dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.removeAllUpdateListeners();
7658dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.addUpdateListener(new AnimatorUpdateListener() {
7668dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
7678dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
7687bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
7697bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float alpha = 1 - percent;
7707bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setAlpha(alpha);
7718dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
7728dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        });
7738dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.addListener(new AnimatorListenerAdapter() {
7748dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void onAnimationEnd(Animator animation) {
7757bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                if (mDropView != null) {
776043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mDragController.onDeferredEndDrag(mDropView);
7777bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                }
7788dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                mDropView = null;
779ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                invalidate();
7808dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
7818dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        });
7828dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.start();
7838dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    }
7848dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
785716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    @Override
7868b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewAdded(View parent, View child) {
78721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
78821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
78921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
79021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
7918b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewRemoved(View parent, View child) {
79221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
79321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
79421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
79521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    private void updateChildIndices() {
79621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        if (mLauncher != null) {
79721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            mWorkspaceIndex = indexOfChild(mLauncher.getWorkspace());
798ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen            mQsbIndex = indexOfChild(mLauncher.getSearchBar());
79921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
80021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
80121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
80221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
80321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    protected int getChildDrawingOrder(int childCount, int i) {
804e29c55ac322f3386327fa5b61e79b00ba3e5d428Adam Cohen        // TODO: We have turned off this custom drawing order because it now effects touch
805e29c55ac322f3386327fa5b61e79b00ba3e5d428Adam Cohen        // dispatch order. We need to sort that issue out and then decide how to go about this.
806cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        if (true || LauncherAppState.isScreenLandscape(getContext()) ||
807e29c55ac322f3386327fa5b61e79b00ba3e5d428Adam Cohen                mWorkspaceIndex == -1 || mQsbIndex == -1 ||
80821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen                mLauncher.getWorkspace().isDrawingBackgroundGradient()) {
80921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
81021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
81121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
81221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // This ensures that the workspace is drawn above the hotseat and qsb,
81321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // except when the workspace is drawing a background gradient, in which
81421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // case we want the workspace to stay behind these elements.
815ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        if (i == mQsbIndex) {
81621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return mWorkspaceIndex;
81721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        } else if (i == mWorkspaceIndex) {
818ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen            return mQsbIndex;
81921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        } else {
82021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
82121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
82221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
823360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
824360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    private boolean mInScrollArea;
825360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    private Drawable mLeftHoverDrawable;
826360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    private Drawable mRightHoverDrawable;
827360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
828360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    void onEnterScrollArea(int direction) {
829360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        mInScrollArea = true;
830360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        invalidate();
831360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    }
832360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
833360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    void onExitScrollArea() {
834360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        mInScrollArea = false;
835360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        invalidate();
836360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    }
837360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
838fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung    /**
839fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung     * Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api.
840fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung     */
841fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung    private boolean isLayoutRtl() {
842fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
843fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung    }
844fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung
845360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    @Override
846360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    protected void dispatchDraw(Canvas canvas) {
847360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        super.dispatchDraw(canvas);
848360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
849e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        if (mInScrollArea && !LauncherAppState.getInstance().isScreenLarge()) {
850360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            Workspace workspace = mLauncher.getWorkspace();
851360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            int width = workspace.getWidth();
852360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            Rect childRect = new Rect();
853360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            getDescendantRectRelativeToSelf(workspace.getChildAt(0), childRect);
854360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
855360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            int page = workspace.getNextPage();
856fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung            final boolean isRtl = isLayoutRtl();
857fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung            CellLayout leftPage = (CellLayout) workspace.getChildAt(isRtl ? page + 1 : page - 1);
858fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung            CellLayout rightPage = (CellLayout) workspace.getChildAt(isRtl ? page - 1 : page + 1);
859360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
860360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            if (leftPage != null && leftPage.getIsDragOverlapping()) {
861360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                mLeftHoverDrawable.setBounds(0, childRect.top,
862360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                        mLeftHoverDrawable.getIntrinsicWidth(), childRect.bottom);
863360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                mLeftHoverDrawable.draw(canvas);
864360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            } else if (rightPage != null && rightPage.getIsDragOverlapping()) {
865360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                mRightHoverDrawable.setBounds(width - mRightHoverDrawable.getIntrinsicWidth(),
866360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                        childRect.top, width, childRect.bottom);
867360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                mRightHoverDrawable.draw(canvas);
868360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            }
869360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        }
870360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    }
87131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
872