DragController.java revision a2413751e3a698aef9c87411a639637883856939
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 1900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.content.Context; 2000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Bitmap; 21b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chungimport android.graphics.Point; 22043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.graphics.PointF; 2300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Rect; 2400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.os.Handler; 250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.os.IBinder; 2600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.os.Vibrator; 2700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.util.Log; 2800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.KeyEvent; 2900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.MotionEvent; 30043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.view.VelocityTracker; 310280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.view.View; 32a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroyimport android.view.ViewConfiguration; 3300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.inputmethod.InputMethodManager; 3400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 35120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohenimport com.android.launcher.R; 36c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen 37c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohenimport java.util.ArrayList; 3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/** 4000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Class for initiating a drag within a view or across multiple views. 4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 4200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratopublic class DragController { 43ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy @SuppressWarnings({"UnusedDeclaration"}) 442e5c432a0aa7e83031575df73bed43a297e2eed3Joe Onorato private static final String TAG = "Launcher.DragController"; 452e5c432a0aa7e83031575df73bed43a297e2eed3Joe Onorato 4600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** Indicates the drag is a move. */ 4700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public static int DRAG_ACTION_MOVE = 0; 4800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 4900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** Indicates the drag is a copy. */ 5000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public static int DRAG_ACTION_COPY = 1; 5100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 52aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung private static final int SCROLL_DELAY = 500; 53aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung private static final int RESCROLL_DELAY = 750; 5461b0c69d3fe331d3de338322396d5de691d58613Winson Chung private static final int VIBRATE_DURATION = 15; 5500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 5600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private static final boolean PROFILE_DRAWING_DURING_DRAG = false; 5700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 5800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private static final int SCROLL_OUTSIDE_ZONE = 0; 5900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private static final int SCROLL_WAITING_IN_ZONE = 1; 6000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 6154fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy static final int SCROLL_NONE = -1; 621262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy static final int SCROLL_LEFT = 0; 631262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy static final int SCROLL_RIGHT = 1; 6400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 65043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private static final float MAX_FLING_DEGREES = 35f; 66043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private static final int FLING_TO_DELETE_THRESHOLD_Y_VELOCITY = -1400; 67043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 688dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen private Launcher mLauncher; 6900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private Handler mHandler; 7000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private final Vibrator mVibrator = new Vibrator(); 7100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 7200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato // temporaries to avoid gc thrash 7300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private Rect mRectTemp = new Rect(); 7400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private final int[] mCoordinatesTemp = new int[2]; 7500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 7600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** Whether or not we're dragging. */ 7700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private boolean mDragging; 7800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 7900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** X coordinate of the down event. */ 80e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen private int mMotionDownX; 8100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 8200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** Y coordinate of the down event. */ 83e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen private int mMotionDownY; 8400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 85658db74c24817892f1a379b16620744f38f60e40Joe Onorato /** the area at the edge of the screen that makes the workspace go left 86658db74c24817892f1a379b16620744f38f60e40Joe Onorato * or right while you're dragging. 87658db74c24817892f1a379b16620744f38f60e40Joe Onorato */ 88658db74c24817892f1a379b16620744f38f60e40Joe Onorato private int mScrollZone; 89658db74c24817892f1a379b16620744f38f60e40Joe Onorato 909932a9b1e66fed4b5f38ce50f13d56331bbdcd7eAdam Cohen private DropTarget.DragObject mDragObject; 9100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 9200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** Who can receive drop events */ 9300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private ArrayList<DropTarget> mDropTargets = new ArrayList<DropTarget>(); 944ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy private ArrayList<DragListener> mListeners = new ArrayList<DragListener>(); 95043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private DropTarget mFlingToDeleteDropTarget; 9600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 9700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** The window token used as the parent for the DragView. */ 9800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private IBinder mWindowToken; 9900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 10000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** The view that will be scrolled when dragging to the left and right edges of the screen. */ 10100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private View mScrollView; 10200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 103ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy private View mMoveTarget; 104ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy 10500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private DragScroller mDragScroller; 10600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private int mScrollState = SCROLL_OUTSIDE_ZONE; 10700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private ScrollRunnable mScrollRunnable = new ScrollRunnable(); 10800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 10900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private DropTarget mLastDropTarget; 11000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 11100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private InputMethodManager mInputMethodManager; 11200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 113a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy private int mLastTouch[] = new int[2]; 114a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy private int mDistanceSinceScroll = 0; 115a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy 116273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung private int mTmpPoint[] = new int[2]; 117273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung private Rect mDragLayerRect = new Rect(); 118273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung 119043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung protected int mFlingToDeleteThresholdVelocity; 120043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private VelocityTracker mVelocityTracker; 121043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Interface to receive notifications when a drag starts or stops 12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project interface DragListener { 12631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * A drag has begun 12931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param source An object representing where the drag originated 13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param info The data associated with the object that is being dragged 13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param dragAction The drag action: either {@link DragController#DRAG_ACTION_MOVE} 13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * or {@link DragController#DRAG_ACTION_COPY} 13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 1355162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato void onDragStart(DragSource source, Object info, int dragAction); 13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 138e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung * The drag has ended 13931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 14031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project void onDragEnd(); 14131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 14231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 14331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 14400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Used to create a new DragLayer from XML. 14500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * 14600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * @param context The application's context. 14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 1488dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen public DragController(Launcher launcher) { 1498dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mLauncher = launcher; 15000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mHandler = new Handler(); 1518dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mScrollZone = launcher.getResources().getDimensionPixelSize(R.dimen.scroll_zone); 152043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mVelocityTracker = VelocityTracker.obtain(); 153043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 154043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float density = launcher.getResources().getDisplayMetrics().density; 155043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFlingToDeleteThresholdVelocity = (int) (FLING_TO_DELETE_THRESHOLD_Y_VELOCITY * density); 15600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 15731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 1581262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy public boolean dragging() { 1591262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy return mDragging; 1601262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy } 1611262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy 16231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 1635162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato * Starts a drag. 164a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * 16531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param v The view that is being dragged 16631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param source An object representing where the drag originated 167ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy * @param dragInfo The data associated with the object that is being dragged 16831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or 16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * {@link #DRAG_ACTION_COPY} 17031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 17100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public void startDrag(View v, DragSource source, Object dragInfo, int dragAction) { 172a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka startDrag(v, source, dragInfo, dragAction, null); 173a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka } 174a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka 175a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka /** 176a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * Starts a drag. 177a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * 178a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * @param v The view that is being dragged 179a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * @param source An object representing where the drag originated 180a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * @param dragInfo The data associated with the object that is being dragged 181a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or 182a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * {@link #DRAG_ACTION_COPY} 183a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * @param dragRegion Coordinates within the bitmap b for the position of item being dragged. 184a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * Makes dragging feel more precise, e.g. you can clip out a transparent border 185a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka */ 186a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka public void startDrag(View v, DragSource source, Object dragInfo, int dragAction, 187a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka Rect dragRegion) { 1885162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato Bitmap b = getViewBitmap(v); 1895162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato 1903f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler if (b == null) { 1913f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler // out of memory? 1923f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler return; 1933f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler } 1943f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler 1955162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato int[] loc = mCoordinatesTemp; 1968dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mLauncher.getDragLayer().getLocationInDragLayer(v, loc); 1978dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen int dragLayerX = loc[0]; 1988dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen int dragLayerY = loc[1]; 1995162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato 20072d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung startDrag(b, dragLayerX, dragLayerY, source, dragInfo, dragAction, null, dragRegion, 1f); 2015162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato b.recycle(); 2025162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato 2035162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato if (dragAction == DRAG_ACTION_MOVE) { 2045162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato v.setVisibility(View.GONE); 2055162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato } 2065162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato } 2075162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato 2085162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato /** 2095162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato * Starts a drag. 210a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * 211e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung * @param v The view that is being dragged 212e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung * @param bmp The bitmap that represents the view being dragged 213e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung * @param source An object representing where the drag originated 214e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung * @param dragInfo The data associated with the object that is being dragged 215e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or 216e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung * {@link #DRAG_ACTION_COPY} 217e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung * @param dragRegion Coordinates within the bitmap b for the position of item being dragged. 218e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung * Makes dragging feel more precise, e.g. you can clip out a transparent border 219e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung */ 220e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo, int dragAction, 22172d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung Rect dragRegion, float initialDragViewScale) { 222e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung int[] loc = mCoordinatesTemp; 2238dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mLauncher.getDragLayer().getLocationInDragLayer(v, loc); 22472d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung int dragLayerX = loc[0] + v.getPaddingLeft() + 22572d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung (int) ((initialDragViewScale * bmp.getWidth() - bmp.getWidth()) / 2); 22672d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung int dragLayerY = loc[1] + v.getPaddingTop() + 22772d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung (int) ((initialDragViewScale * bmp.getHeight() - bmp.getHeight()) / 2); 228e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung 22972d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction, null, dragRegion, 23072d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung initialDragViewScale); 231e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung 232e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung if (dragAction == DRAG_ACTION_MOVE) { 233e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung v.setVisibility(View.GONE); 234e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung } 235e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung } 236e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung 237e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung /** 238e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung * Starts a drag. 239e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung * 2405162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato * @param b The bitmap to display as the drag image. It will be re-scaled to the 2415162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato * enlarged size. 2428dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen * @param dragLayerX The x position in the DragLayer of the left-top of the bitmap. 2438dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap. 2445162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato * @param source An object representing where the drag originated 245ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy * @param dragInfo The data associated with the object that is being dragged 2465162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or 2475162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato * {@link #DRAG_ACTION_COPY} 248a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * @param dragRegion Coordinates within the bitmap b for the position of item being dragged. 249a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka * Makes dragging feel more precise, e.g. you can clip out a transparent border 250a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka */ 2518dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen public void startDrag(Bitmap b, int dragLayerX, int dragLayerY, 25272d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion, 25372d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung float initialDragViewScale) { 25400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (PROFILE_DRAWING_DURING_DRAG) { 25500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato android.os.Debug.startMethodTracing("Launcher"); 25600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 25700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 25800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato // Hide soft keyboard, if visible 25900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (mInputMethodManager == null) { 26000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mInputMethodManager = (InputMethodManager) 2618dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mLauncher.getSystemService(Context.INPUT_METHOD_SERVICE); 26200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 26300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0); 26400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 2654ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy for (DragListener listener : mListeners) { 2664ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy listener.onDragStart(source, dragInfo, dragAction); 26700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 26800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 2698dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen final int registrationX = mMotionDownX - dragLayerX; 2708dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen final int registrationY = mMotionDownY - dragLayerY; 27100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 272a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left; 273a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top; 274e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen 27500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDragging = true; 276cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen 2779932a9b1e66fed4b5f38ce50f13d56331bbdcd7eAdam Cohen mDragObject = new DropTarget.DragObject(); 2789932a9b1e66fed4b5f38ce50f13d56331bbdcd7eAdam Cohen 279bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mDragObject.dragComplete = false; 2808dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft); 2818dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop); 282cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mDragObject.dragSource = source; 283cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mDragObject.dragInfo = dragInfo; 28400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 28500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mVibrator.vibrate(VIBRATE_DURATION); 28600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 2878dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX, 28872d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung registrationY, 0, 0, b.getWidth(), b.getHeight(), initialDragViewScale); 289a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka 290b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung if (dragOffset != null) { 291b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung dragView.setDragVisualizeOffset(new Point(dragOffset)); 292b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung } 293a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka if (dragRegion != null) { 294e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen dragView.setDragRegion(new Rect(dragRegion)); 295a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka } 296a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka 2978dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen dragView.show(mMotionDownX, mMotionDownY); 2988dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen handleMoveEvent(mMotionDownX, mMotionDownY); 29900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 30000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 30100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** 30200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Draw the view into a bitmap. 30300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato */ 304120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen Bitmap getViewBitmap(View v) { 30500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato v.clearFocus(); 30600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato v.setPressed(false); 30700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 30800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato boolean willNotCache = v.willNotCacheDrawing(); 30900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato v.setWillNotCacheDrawing(false); 31000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 31100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato // Reset the drawing cache background color to fully transparent 31200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato // for the duration of this operation 31300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato int color = v.getDrawingCacheBackgroundColor(); 31400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato v.setDrawingCacheBackgroundColor(0); 315120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen float alpha = v.getAlpha(); 316120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen v.setAlpha(1.0f); 31700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 31800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (color != 0) { 31900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato v.destroyDrawingCache(); 32000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 32100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato v.buildDrawingCache(); 32200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato Bitmap cacheBitmap = v.getDrawingCache(); 3233f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler if (cacheBitmap == null) { 3243f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler Log.e(TAG, "failed getViewBitmap(" + v + ")", new RuntimeException()); 3253f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler return null; 3263f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler } 32700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 32800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato Bitmap bitmap = Bitmap.createBitmap(cacheBitmap); 32900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 33000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato // Restore the view 33100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato v.destroyDrawingCache(); 332120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen v.setAlpha(alpha); 33300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato v.setWillNotCacheDrawing(willNotCache); 33400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato v.setDrawingCacheBackgroundColor(color); 33500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 33600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato return bitmap; 33700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 33800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 33900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** 34000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Call this from a drag source view like this: 34100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * 34200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * <pre> 34300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * @Override 34400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * public boolean dispatchKeyEvent(KeyEvent event) { 34500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * return mDragController.dispatchKeyEvent(this, event) 34600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * || super.dispatchKeyEvent(event); 34700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * </pre> 34800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato */ 349ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy @SuppressWarnings({"UnusedDeclaration"}) 35000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public boolean dispatchKeyEvent(KeyEvent event) { 35100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato return mDragging; 35200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 35300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 354304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung public boolean isDragging() { 355304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung return mDragging; 356304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung } 357304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung 35824b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato /** 35924b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato * Stop dragging without dropping. 36024b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato */ 36124b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato public void cancelDrag() { 362621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung if (mDragging) { 363c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung if (mLastDropTarget != null) { 364c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung mLastDropTarget.onDragExit(mDragObject); 365c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung } 36641bb19d2775836e30ebf42f681b4617bc71600aaWinson Chung mDragObject.deferDragViewCleanupPostAnimation = false; 36736cc09b07b19198f4ea886583cef462ade27192cAdam Cohen mDragObject.cancelled = true; 368bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mDragObject.dragComplete = true; 369a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung mDragObject.dragSource.onDropCompleted(null, mDragObject, false, false); 370621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung } 37124b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato endDrag(); 37224b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato } 373a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung public void onAppsRemoved(ArrayList<ApplicationInfo> apps, Context context) { 374a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung // Cancel the current drag if we are removing an app that we are dragging 375a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung if (mDragObject != null) { 376a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung Object rawDragInfo = mDragObject.dragInfo; 377a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung if (rawDragInfo instanceof ShortcutInfo) { 378a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung ShortcutInfo dragInfo = (ShortcutInfo) rawDragInfo; 379a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung for (ApplicationInfo info : apps) { 3807bcadad93f97e79d95ae879fe165de2e2371f613Michael Jurka // Added null checks to prevent NPE we've seen in the wild 3817bcadad93f97e79d95ae879fe165de2e2371f613Michael Jurka if (dragInfo != null && 3827bcadad93f97e79d95ae879fe165de2e2371f613Michael Jurka dragInfo.intent != null && 3837bcadad93f97e79d95ae879fe165de2e2371f613Michael Jurka info.intent != null && 3847bcadad93f97e79d95ae879fe165de2e2371f613Michael Jurka dragInfo.intent.getComponent().equals(info.intent.getComponent())) { 385a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung cancelDrag(); 386a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung return; 387a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung } 388a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung } 389a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung } 390a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung } 391a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung } 39224b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato 39300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private void endDrag() { 39400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (mDragging) { 39500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDragging = false; 396aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung clearScrollRunnable(); 397043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung boolean isDeferred = false; 398cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen if (mDragObject.dragView != null) { 399043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung isDeferred = mDragObject.deferDragViewCleanupPostAnimation; 400043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (!isDeferred) { 4017bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDragObject.dragView.remove(); 4027bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung } 403cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mDragObject.dragView = null; 40400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 405043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 406043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Only end the drag if we are not deferred 407043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (!isDeferred) { 408043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung for (DragListener listener : mListeners) { 409043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung listener.onDragEnd(); 410043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 411043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 412043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 413043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 414043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung releaseVelocityTracker(); 415043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 416043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 417043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung /** 418043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * This only gets called as a result of drag view cleanup being deferred in endDrag(); 419043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung */ 420043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung void onDeferredEndDrag(DragView dragView) { 421043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.remove(); 422043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 423043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // If we skipped calling onDragEnd() before, do it now 424043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung for (DragListener listener : mListeners) { 425043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung listener.onDragEnd(); 42600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 42700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 42800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 429a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung void onDeferredEndFling(DropTarget.DragObject d) { 430a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung d.dragSource.onFlingToDeleteCompleted(); 431a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 432a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 43300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** 434273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung * Clamps the position to the drag layer bounds. 435273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung */ 436273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung private int[] getClampedDragLayerPos(float x, float y) { 437273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung mLauncher.getDragLayer().getLocalVisibleRect(mDragLayerRect); 438273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung mTmpPoint[0] = (int) Math.max(mDragLayerRect.left, Math.min(x, mDragLayerRect.right - 1)); 439273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung mTmpPoint[1] = (int) Math.max(mDragLayerRect.top, Math.min(y, mDragLayerRect.bottom - 1)); 440273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung return mTmpPoint; 441273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung } 442273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung 443a2413751e3a698aef9c87411a639637883856939Winson Chung private long mLastTouchUpTime = -1; 444a2413751e3a698aef9c87411a639637883856939Winson Chung long getLastGestureUpTime() { 445a2413751e3a698aef9c87411a639637883856939Winson Chung if (mDragging) { 446a2413751e3a698aef9c87411a639637883856939Winson Chung return System.currentTimeMillis(); 447a2413751e3a698aef9c87411a639637883856939Winson Chung } else { 448a2413751e3a698aef9c87411a639637883856939Winson Chung return mLastTouchUpTime; 449a2413751e3a698aef9c87411a639637883856939Winson Chung } 450a2413751e3a698aef9c87411a639637883856939Winson Chung } 451a2413751e3a698aef9c87411a639637883856939Winson Chung 452a2413751e3a698aef9c87411a639637883856939Winson Chung void resetLastGestureUpTime() { 453a2413751e3a698aef9c87411a639637883856939Winson Chung mLastTouchUpTime = -1; 454a2413751e3a698aef9c87411a639637883856939Winson Chung } 455a2413751e3a698aef9c87411a639637883856939Winson Chung 456273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung /** 45700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Call this from a drag source view. 45800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato */ 45900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public boolean onInterceptTouchEvent(MotionEvent ev) { 4609c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato if (false) { 461a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.d(Launcher.TAG, "DragController.onInterceptTouchEvent " + ev + " mDragging=" 4629c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato + mDragging); 4639c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato } 46400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 465043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Update the velocity tracker 466043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung acquireVelocityTrackerAndAddMovement(ev); 467043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 468043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final int action = ev.getAction(); 469273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY()); 470273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung final int dragLayerX = dragLayerPos[0]; 471273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung final int dragLayerY = dragLayerPos[1]; 47200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 47300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato switch (action) { 47400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato case MotionEvent.ACTION_MOVE: 47500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato break; 47600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato case MotionEvent.ACTION_DOWN: 47700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato // Remember location of down touch 4788dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mMotionDownX = dragLayerX; 4798dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mMotionDownY = dragLayerY; 48000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mLastDropTarget = null; 48100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato break; 48200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato case MotionEvent.ACTION_UP: 483a2413751e3a698aef9c87411a639637883856939Winson Chung mLastTouchUpTime = System.currentTimeMillis(); 48400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (mDragging) { 485043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung PointF vec = isFlingingToDelete(mDragObject.dragSource); 486043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (vec != null) { 487043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec); 488043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } else { 489043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung drop(dragLayerX, dragLayerY); 490043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 49100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 49200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato endDrag(); 49300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato break; 494621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung case MotionEvent.ACTION_CANCEL: 495621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung cancelDrag(); 496621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung break; 49700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 49800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 49900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato return mDragging; 50000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 50100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 50200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** 503ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy * Sets the view that should handle move events. 504ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy */ 505ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy void setMoveTarget(View view) { 506ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy mMoveTarget = view; 507ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy } 508ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy 509ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy public boolean dispatchUnhandledMove(View focused, int direction) { 510ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy return mMoveTarget != null && mMoveTarget.dispatchUnhandledMove(focused, direction); 511ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy } 512ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy 513aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung private void clearScrollRunnable() { 514aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung mHandler.removeCallbacks(mScrollRunnable); 515aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung if (mScrollState == SCROLL_WAITING_IN_ZONE) { 516aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung mScrollState = SCROLL_OUTSIDE_ZONE; 517aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung mScrollRunnable.setDirection(SCROLL_RIGHT); 518aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung mDragScroller.onExitScrollArea(); 519aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung } 520aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung } 521aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung 522de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy private void handleMoveEvent(int x, int y) { 523cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mDragObject.dragView.move(x, y); 524de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy 525de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy // Drop on someone? 526de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy final int[] coordinates = mCoordinatesTemp; 527de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy DropTarget dropTarget = findDropTarget(x, y, coordinates); 528cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mDragObject.x = coordinates[0]; 529cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mDragObject.y = coordinates[1]; 530de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy if (dropTarget != null) { 531cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen DropTarget delegate = dropTarget.getDropTargetDelegate(mDragObject); 532de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy if (delegate != null) { 533de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy dropTarget = delegate; 534de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy } 535de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy 536de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy if (mLastDropTarget != dropTarget) { 537de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy if (mLastDropTarget != null) { 538cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mLastDropTarget.onDragExit(mDragObject); 539de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy } 540cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen dropTarget.onDragEnter(mDragObject); 541de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy } 542cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen dropTarget.onDragOver(mDragObject); 543de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy } else { 544de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy if (mLastDropTarget != null) { 545cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mLastDropTarget.onDragExit(mDragObject); 546de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy } 547de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy } 548de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy mLastDropTarget = dropTarget; 549de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy 550a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy // After a scroll, the touch point will still be in the scroll region. 551a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy // Rather than scrolling immediately, require a bit of twiddling to scroll again 5528dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen final int slop = ViewConfiguration.get(mLauncher).getScaledWindowTouchSlop(); 553a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy mDistanceSinceScroll += 554a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy Math.sqrt(Math.pow(mLastTouch[0] - x, 2) + Math.pow(mLastTouch[1] - y, 2)); 555a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy mLastTouch[0] = x; 556a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy mLastTouch[1] = y; 557aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung final int delay = mDistanceSinceScroll < slop ? RESCROLL_DELAY : SCROLL_DELAY; 558a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy 5593f4e1423804d64a38cb69e4511d7b80783564827Winson Chung if (x < mScrollZone) { 560aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung if (mScrollState == SCROLL_OUTSIDE_ZONE) { 561de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy mScrollState = SCROLL_WAITING_IN_ZONE; 5623e0839e5f830ab7e64223ebe186d97729eda3e22Winson Chung if (mDragScroller.onEnterScrollArea(x, y, SCROLL_LEFT)) { 5633e0839e5f830ab7e64223ebe186d97729eda3e22Winson Chung mScrollRunnable.setDirection(SCROLL_LEFT); 564aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung mHandler.postDelayed(mScrollRunnable, delay); 5653e0839e5f830ab7e64223ebe186d97729eda3e22Winson Chung } 566de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy } 5673f4e1423804d64a38cb69e4511d7b80783564827Winson Chung } else if (x > mScrollView.getWidth() - mScrollZone) { 568aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung if (mScrollState == SCROLL_OUTSIDE_ZONE) { 569de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy mScrollState = SCROLL_WAITING_IN_ZONE; 5703e0839e5f830ab7e64223ebe186d97729eda3e22Winson Chung if (mDragScroller.onEnterScrollArea(x, y, SCROLL_RIGHT)) { 5713e0839e5f830ab7e64223ebe186d97729eda3e22Winson Chung mScrollRunnable.setDirection(SCROLL_RIGHT); 572aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung mHandler.postDelayed(mScrollRunnable, delay); 5733e0839e5f830ab7e64223ebe186d97729eda3e22Winson Chung } 574de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy } 575de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy } else { 576aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung clearScrollRunnable(); 577de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy } 578de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy } 579de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy 5803bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung public void forceMoveEvent() { 5813bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung if (mDragging) { 5823bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung handleMoveEvent(mDragObject.x, mDragObject.y); 5833bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung } 5843bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung } 5853bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung 586ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy /** 58700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Call this from a drag source view. 58800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato */ 58900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public boolean onTouchEvent(MotionEvent ev) { 59000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (!mDragging) { 59100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato return false; 59200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 59300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 594043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Update the velocity tracker 595043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung acquireVelocityTrackerAndAddMovement(ev); 596043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 59700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato final int action = ev.getAction(); 598273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY()); 599273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung final int dragLayerX = dragLayerPos[0]; 600273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung final int dragLayerY = dragLayerPos[1]; 60100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 60200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato switch (action) { 60300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato case MotionEvent.ACTION_DOWN: 60400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato // Remember where the motion event started 6058dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mMotionDownX = dragLayerX; 6068dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mMotionDownY = dragLayerY; 60700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 6088dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen if ((dragLayerX < mScrollZone) || (dragLayerX > mScrollView.getWidth() - mScrollZone)) { 60900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mScrollState = SCROLL_WAITING_IN_ZONE; 61000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY); 61100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } else { 61200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mScrollState = SCROLL_OUTSIDE_ZONE; 61300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 61400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato break; 61500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato case MotionEvent.ACTION_MOVE: 6168dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen handleMoveEvent(dragLayerX, dragLayerY); 61700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato break; 61800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato case MotionEvent.ACTION_UP: 619b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy // Ensure that we've processed a move event at the current pointer location. 6208dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen handleMoveEvent(dragLayerX, dragLayerY); 6213bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung mHandler.removeCallbacks(mScrollRunnable); 622043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 62300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (mDragging) { 624043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung PointF vec = isFlingingToDelete(mDragObject.dragSource); 625043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (vec != null) { 626043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec); 627043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } else { 628043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung drop(dragLayerX, dragLayerY); 629043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 63000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 63100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato endDrag(); 63200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato break; 63300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato case MotionEvent.ACTION_CANCEL: 6343bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung mHandler.removeCallbacks(mScrollRunnable); 63524b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato cancelDrag(); 636621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung break; 63700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 63800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 63900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato return true; 64000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 64100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 642043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung /** 643043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * Determines whether the user flung the current item to delete it. 644043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * 645043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * @return the vector at which the item was flung, or null if no fling was detected. 646043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung */ 647043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private PointF isFlingingToDelete(DragSource source) { 648043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mFlingToDeleteDropTarget == null) return null; 649043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (!source.supportsFlingToDelete()) return null; 650043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 651043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung ViewConfiguration config = ViewConfiguration.get(mLauncher); 652043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mVelocityTracker.computeCurrentVelocity(1000, config.getScaledMaximumFlingVelocity()); 653043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 654043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mVelocityTracker.getYVelocity() < mFlingToDeleteThresholdVelocity) { 655043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Do a quick dot product test to ensure that we are flinging upwards 656043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung PointF vel = new PointF(mVelocityTracker.getXVelocity(), 657043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mVelocityTracker.getYVelocity()); 658043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung PointF upVec = new PointF(0f, -1f); 659043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float theta = (float) Math.acos(((vel.x * upVec.x) + (vel.y * upVec.y)) / 660043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung (vel.length() * upVec.length())); 661043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (theta <= Math.toRadians(MAX_FLING_DEGREES)) { 662043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return vel; 663043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 664043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 665043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return null; 666043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 667043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 668043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private void dropOnFlingToDeleteTarget(float x, float y, PointF vel) { 669043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final int[] coordinates = mCoordinatesTemp; 670043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 671043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDragObject.x = coordinates[0]; 672043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDragObject.y = coordinates[1]; 673043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 674043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Clean up dragging on the target if it's not the current fling delete target otherwise, 675043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // start dragging to it. 676043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mLastDropTarget != null && mFlingToDeleteDropTarget != mLastDropTarget) { 677043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mLastDropTarget.onDragExit(mDragObject); 678043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 679043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 680043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Drop onto the fling-to-delete target 681043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung boolean accepted = false; 682043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFlingToDeleteDropTarget.onDragEnter(mDragObject); 683232decb008661d82ed2ca6d5f3080ee5a50d3be1Winson Chung // We must set dragComplete to true _only_ after we "enter" the fling-to-delete target for 684232decb008661d82ed2ca6d5f3080ee5a50d3be1Winson Chung // "drop" 685232decb008661d82ed2ca6d5f3080ee5a50d3be1Winson Chung mDragObject.dragComplete = true; 686043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFlingToDeleteDropTarget.onDragExit(mDragObject); 687043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mFlingToDeleteDropTarget.acceptDrop(mDragObject)) { 688043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFlingToDeleteDropTarget.onFlingToDelete(mDragObject, mDragObject.x, mDragObject.y, 689043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung vel); 690043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung accepted = true; 691043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 692a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung mDragObject.dragSource.onDropCompleted((View) mFlingToDeleteDropTarget, mDragObject, true, 693043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung accepted); 694043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 695043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 696b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy private void drop(float x, float y) { 69700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato final int[] coordinates = mCoordinatesTemp; 698b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy final DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates); 69900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 700cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mDragObject.x = coordinates[0]; 701cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mDragObject.y = coordinates[1]; 702b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy boolean accepted = false; 70300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (dropTarget != null) { 704bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mDragObject.dragComplete = true; 705cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen dropTarget.onDragExit(mDragObject); 706cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen if (dropTarget.acceptDrop(mDragObject)) { 707cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen dropTarget.onDrop(mDragObject); 708b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy accepted = true; 70900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 71000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 711a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject, false, accepted); 71200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 71300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 71400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) { 71500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato final Rect r = mRectTemp; 71600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 71700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato final ArrayList<DropTarget> dropTargets = mDropTargets; 71800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato final int count = dropTargets.size(); 71900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato for (int i=count-1; i>=0; i--) { 720440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy DropTarget target = dropTargets.get(i); 7210280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka if (!target.isDropEnabled()) 7220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka continue; 7230280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka 72400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato target.getHitRect(r); 725440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy 7268dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen // Convert the hit rect to DragLayer coordinates 7278dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen target.getLocationInDragLayer(dropCoordinates); 72800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop()); 729440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy 730cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mDragObject.x = x; 731cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen mDragObject.y = y; 73200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (r.contains(x, y)) { 733cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen DropTarget delegate = target.getDropTargetDelegate(mDragObject); 734440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy if (delegate != null) { 735440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy target = delegate; 7368dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen target.getLocationInDragLayer(dropCoordinates); 737440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy } 738440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy 739440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy // Make dropCoordinates relative to the DropTarget 74000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato dropCoordinates[0] = x - dropCoordinates[0]; 74100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato dropCoordinates[1] = y - dropCoordinates[1]; 742440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy 74300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato return target; 74400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 74500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 74600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato return null; 74700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 74800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 74900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public void setDragScoller(DragScroller scroller) { 75000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDragScroller = scroller; 75100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 75200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 75300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public void setWindowToken(IBinder token) { 75400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mWindowToken = token; 75500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 75600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 75731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 75831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Sets the drag listner which will be notified when a drag starts or ends. 75931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 7604ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy public void addDragListener(DragListener l) { 7614ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy mListeners.add(l); 76200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 76300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 76431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 76531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Remove a previously installed drag listener. 76631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 76700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public void removeDragListener(DragListener l) { 7684ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy mListeners.remove(l); 76900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 77000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 77100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** 77200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Add a DropTarget to the list of potential places to receive drop events. 77300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato */ 77400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public void addDropTarget(DropTarget target) { 77500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDropTargets.add(target); 77600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 77700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 77800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** 77900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Don't send drop events to <em>target</em> any more. 78000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato */ 78100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public void removeDropTarget(DropTarget target) { 78200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDropTargets.remove(target); 78300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 78400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 78500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato /** 786043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * Sets the current fling-to-delete drop target. 787043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung */ 788043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public void setFlingToDeleteDropTarget(DropTarget target) { 789043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFlingToDeleteDropTarget = target; 790043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 791043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 792043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) { 793043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mVelocityTracker == null) { 794043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mVelocityTracker = VelocityTracker.obtain(); 795043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 796043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mVelocityTracker.addMovement(ev); 797043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 798043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 799043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private void releaseVelocityTracker() { 800043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mVelocityTracker != null) { 801043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mVelocityTracker.recycle(); 802043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mVelocityTracker = null; 803043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 804043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 805043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 806043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung /** 80700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Set which view scrolls for touch events near the edge of the screen. 80800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato */ 80900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public void setScrollView(View v) { 81000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mScrollView = v; 81100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 81200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 8135f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy DragView getDragView() { 814cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen return mDragObject.dragView; 8155f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy } 8165f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy 81700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private class ScrollRunnable implements Runnable { 81800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato private int mDirection; 81900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 82000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato ScrollRunnable() { 82100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 82200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 82300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public void run() { 82400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (mDragScroller != null) { 82500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (mDirection == SCROLL_LEFT) { 82600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDragScroller.scrollLeft(); 82700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } else { 82800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDragScroller.scrollRight(); 82900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 83000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mScrollState = SCROLL_OUTSIDE_ZONE; 831a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy mDistanceSinceScroll = 0; 832a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy mDragScroller.onExitScrollArea(); 833aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung 834aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung if (isDragging()) { 835aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung // Force an update so that we can requeue the scroller if necessary 8363bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung forceMoveEvent(); 837aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung } 83800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 83900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 84000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 84100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato void setDirection(int direction) { 84200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDirection = direction; 84300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 84400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 84531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 846