mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-20 11:18:21 +00:00
709 lines
24 KiB
Java
709 lines
24 KiB
Java
/*
|
|
* Copyright (C) 2008 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.launcher2;
|
|
|
|
import android.content.Context;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.Point;
|
|
import android.graphics.Rect;
|
|
import android.graphics.RectF;
|
|
import android.os.Handler;
|
|
import android.os.IBinder;
|
|
import android.os.Vibrator;
|
|
import android.util.Log;
|
|
import android.view.KeyEvent;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
import android.view.ViewConfiguration;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
|
|
import com.android.launcher.R;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
/**
|
|
* Class for initiating a drag within a view or across multiple views.
|
|
*/
|
|
public class DragController {
|
|
@SuppressWarnings({"UnusedDeclaration"})
|
|
private static final String TAG = "Launcher.DragController";
|
|
|
|
/** Indicates the drag is a move. */
|
|
public static int DRAG_ACTION_MOVE = 0;
|
|
|
|
/** Indicates the drag is a copy. */
|
|
public static int DRAG_ACTION_COPY = 1;
|
|
|
|
private static final int SCROLL_DELAY = 600;
|
|
private static final int VIBRATE_DURATION = 35;
|
|
|
|
private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
|
|
|
|
private static final int SCROLL_OUTSIDE_ZONE = 0;
|
|
private static final int SCROLL_WAITING_IN_ZONE = 1;
|
|
|
|
static final int SCROLL_NONE = -1;
|
|
static final int SCROLL_LEFT = 0;
|
|
static final int SCROLL_RIGHT = 1;
|
|
|
|
private Launcher mLauncher;
|
|
private Handler mHandler;
|
|
private final Vibrator mVibrator = new Vibrator();
|
|
|
|
// temporaries to avoid gc thrash
|
|
private Rect mRectTemp = new Rect();
|
|
private final int[] mCoordinatesTemp = new int[2];
|
|
|
|
/** Whether or not we're dragging. */
|
|
private boolean mDragging;
|
|
|
|
/** X coordinate of the down event. */
|
|
private int mMotionDownX;
|
|
|
|
/** Y coordinate of the down event. */
|
|
private int mMotionDownY;
|
|
|
|
/** the area at the edge of the screen that makes the workspace go left
|
|
* or right while you're dragging.
|
|
*/
|
|
private int mScrollZone;
|
|
|
|
private DropTarget.DragObject mDragObject;
|
|
|
|
/** Who can receive drop events */
|
|
private ArrayList<DropTarget> mDropTargets = new ArrayList<DropTarget>();
|
|
|
|
private ArrayList<DragListener> mListeners = new ArrayList<DragListener>();
|
|
|
|
/** The window token used as the parent for the DragView. */
|
|
private IBinder mWindowToken;
|
|
|
|
/** The view that will be scrolled when dragging to the left and right edges of the screen. */
|
|
private View mScrollView;
|
|
|
|
private View mMoveTarget;
|
|
|
|
private DragScroller mDragScroller;
|
|
private int mScrollState = SCROLL_OUTSIDE_ZONE;
|
|
private ScrollRunnable mScrollRunnable = new ScrollRunnable();
|
|
|
|
private RectF mDeleteRegion;
|
|
private DropTarget mLastDropTarget;
|
|
|
|
private InputMethodManager mInputMethodManager;
|
|
|
|
private int mLastTouch[] = new int[2];
|
|
private int mDistanceSinceScroll = 0;
|
|
|
|
private int mTmpPoint[] = new int[2];
|
|
private Rect mDragLayerRect = new Rect();
|
|
|
|
/**
|
|
* Interface to receive notifications when a drag starts or stops
|
|
*/
|
|
interface DragListener {
|
|
|
|
/**
|
|
* A drag has begun
|
|
*
|
|
* @param source An object representing where the drag originated
|
|
* @param info The data associated with the object that is being dragged
|
|
* @param dragAction The drag action: either {@link DragController#DRAG_ACTION_MOVE}
|
|
* or {@link DragController#DRAG_ACTION_COPY}
|
|
*/
|
|
void onDragStart(DragSource source, Object info, int dragAction);
|
|
|
|
/**
|
|
* The drag has ended
|
|
*/
|
|
void onDragEnd();
|
|
}
|
|
|
|
/**
|
|
* Used to create a new DragLayer from XML.
|
|
*
|
|
* @param context The application's context.
|
|
*/
|
|
public DragController(Launcher launcher) {
|
|
mLauncher = launcher;
|
|
mHandler = new Handler();
|
|
mScrollZone = launcher.getResources().getDimensionPixelSize(R.dimen.scroll_zone);
|
|
}
|
|
|
|
public boolean dragging() {
|
|
return mDragging;
|
|
}
|
|
|
|
/**
|
|
* Starts a drag.
|
|
*
|
|
* @param v The view that is being dragged
|
|
* @param source An object representing where the drag originated
|
|
* @param dragInfo The data associated with the object that is being dragged
|
|
* @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
|
|
* {@link #DRAG_ACTION_COPY}
|
|
*/
|
|
public void startDrag(View v, DragSource source, Object dragInfo, int dragAction) {
|
|
startDrag(v, source, dragInfo, dragAction, null);
|
|
}
|
|
|
|
/**
|
|
* Starts a drag.
|
|
*
|
|
* @param v The view that is being dragged
|
|
* @param source An object representing where the drag originated
|
|
* @param dragInfo The data associated with the object that is being dragged
|
|
* @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
|
|
* {@link #DRAG_ACTION_COPY}
|
|
* @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
|
|
* Makes dragging feel more precise, e.g. you can clip out a transparent border
|
|
*/
|
|
public void startDrag(View v, DragSource source, Object dragInfo, int dragAction,
|
|
Rect dragRegion) {
|
|
Bitmap b = getViewBitmap(v);
|
|
|
|
if (b == null) {
|
|
// out of memory?
|
|
return;
|
|
}
|
|
|
|
int[] loc = mCoordinatesTemp;
|
|
mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
|
|
int dragLayerX = loc[0];
|
|
int dragLayerY = loc[1];
|
|
|
|
startDrag(b, dragLayerX, dragLayerY, source, dragInfo, dragAction, null, dragRegion);
|
|
b.recycle();
|
|
|
|
if (dragAction == DRAG_ACTION_MOVE) {
|
|
v.setVisibility(View.GONE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Starts a drag.
|
|
*
|
|
* @param v The view that is being dragged
|
|
* @param bmp The bitmap that represents the view being dragged
|
|
* @param source An object representing where the drag originated
|
|
* @param dragInfo The data associated with the object that is being dragged
|
|
* @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
|
|
* {@link #DRAG_ACTION_COPY}
|
|
* @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
|
|
* Makes dragging feel more precise, e.g. you can clip out a transparent border
|
|
*/
|
|
public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo, int dragAction,
|
|
Rect dragRegion) {
|
|
int[] loc = mCoordinatesTemp;
|
|
mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
|
|
int dragLayerX = loc[0];
|
|
int dragLayerY = loc[1];
|
|
|
|
startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction, null, dragRegion);
|
|
|
|
if (dragAction == DRAG_ACTION_MOVE) {
|
|
v.setVisibility(View.GONE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Starts a drag.
|
|
*
|
|
* @param b The bitmap to display as the drag image. It will be re-scaled to the
|
|
* enlarged size.
|
|
* @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.
|
|
* @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
|
|
* @param source An object representing where the drag originated
|
|
* @param dragInfo The data associated with the object that is being dragged
|
|
* @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
|
|
* {@link #DRAG_ACTION_COPY}
|
|
*/
|
|
public void startDrag(Bitmap b, int dragLayerX, int dragLayerY,
|
|
DragSource source, Object dragInfo, int dragAction) {
|
|
startDrag(b, dragLayerX, dragLayerY, source, dragInfo, dragAction, null, null);
|
|
}
|
|
|
|
/**
|
|
* Starts a drag.
|
|
*
|
|
* @param b The bitmap to display as the drag image. It will be re-scaled to the
|
|
* enlarged size.
|
|
* @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.
|
|
* @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
|
|
* @param source An object representing where the drag originated
|
|
* @param dragInfo The data associated with the object that is being dragged
|
|
* @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
|
|
* {@link #DRAG_ACTION_COPY}
|
|
* @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
|
|
* Makes dragging feel more precise, e.g. you can clip out a transparent border
|
|
*/
|
|
public void startDrag(Bitmap b, int dragLayerX, int dragLayerY,
|
|
DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion) {
|
|
if (PROFILE_DRAWING_DURING_DRAG) {
|
|
android.os.Debug.startMethodTracing("Launcher");
|
|
}
|
|
|
|
// Hide soft keyboard, if visible
|
|
if (mInputMethodManager == null) {
|
|
mInputMethodManager = (InputMethodManager)
|
|
mLauncher.getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
}
|
|
mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0);
|
|
|
|
for (DragListener listener : mListeners) {
|
|
listener.onDragStart(source, dragInfo, dragAction);
|
|
}
|
|
|
|
final int registrationX = mMotionDownX - dragLayerX;
|
|
final int registrationY = mMotionDownY - dragLayerY;
|
|
|
|
final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
|
|
final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
|
|
|
|
mDragging = true;
|
|
|
|
mDragObject = new DropTarget.DragObject();
|
|
|
|
mDragObject.dragComplete = false;
|
|
mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
|
|
mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
|
|
mDragObject.dragSource = source;
|
|
mDragObject.dragInfo = dragInfo;
|
|
|
|
mVibrator.vibrate(VIBRATE_DURATION);
|
|
|
|
final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,
|
|
registrationY, 0, 0, b.getWidth(), b.getHeight());
|
|
|
|
if (dragOffset != null) {
|
|
dragView.setDragVisualizeOffset(new Point(dragOffset));
|
|
}
|
|
if (dragRegion != null) {
|
|
dragView.setDragRegion(new Rect(dragRegion));
|
|
}
|
|
|
|
dragView.show(mMotionDownX, mMotionDownY);
|
|
handleMoveEvent(mMotionDownX, mMotionDownY);
|
|
}
|
|
|
|
/**
|
|
* Draw the view into a bitmap.
|
|
*/
|
|
Bitmap getViewBitmap(View v) {
|
|
v.clearFocus();
|
|
v.setPressed(false);
|
|
|
|
boolean willNotCache = v.willNotCacheDrawing();
|
|
v.setWillNotCacheDrawing(false);
|
|
|
|
// Reset the drawing cache background color to fully transparent
|
|
// for the duration of this operation
|
|
int color = v.getDrawingCacheBackgroundColor();
|
|
v.setDrawingCacheBackgroundColor(0);
|
|
float alpha = v.getAlpha();
|
|
v.setAlpha(1.0f);
|
|
|
|
if (color != 0) {
|
|
v.destroyDrawingCache();
|
|
}
|
|
v.buildDrawingCache();
|
|
Bitmap cacheBitmap = v.getDrawingCache();
|
|
if (cacheBitmap == null) {
|
|
Log.e(TAG, "failed getViewBitmap(" + v + ")", new RuntimeException());
|
|
return null;
|
|
}
|
|
|
|
Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
|
|
|
|
// Restore the view
|
|
v.destroyDrawingCache();
|
|
v.setAlpha(alpha);
|
|
v.setWillNotCacheDrawing(willNotCache);
|
|
v.setDrawingCacheBackgroundColor(color);
|
|
|
|
return bitmap;
|
|
}
|
|
|
|
/**
|
|
* Call this from a drag source view like this:
|
|
*
|
|
* <pre>
|
|
* @Override
|
|
* public boolean dispatchKeyEvent(KeyEvent event) {
|
|
* return mDragController.dispatchKeyEvent(this, event)
|
|
* || super.dispatchKeyEvent(event);
|
|
* </pre>
|
|
*/
|
|
@SuppressWarnings({"UnusedDeclaration"})
|
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
|
return mDragging;
|
|
}
|
|
|
|
public boolean isDragging() {
|
|
return mDragging;
|
|
}
|
|
|
|
/**
|
|
* Stop dragging without dropping.
|
|
*/
|
|
public void cancelDrag() {
|
|
if (mDragging) {
|
|
if (mLastDropTarget != null) {
|
|
mLastDropTarget.onDragExit(mDragObject);
|
|
}
|
|
mDragObject.cancelled = true;
|
|
mDragObject.dragComplete = true;
|
|
mDragObject.dragSource.onDropCompleted(null, mDragObject, false);
|
|
}
|
|
endDrag();
|
|
}
|
|
public void onAppsRemoved(ArrayList<ApplicationInfo> apps, Context context) {
|
|
// Cancel the current drag if we are removing an app that we are dragging
|
|
if (mDragObject != null) {
|
|
Object rawDragInfo = mDragObject.dragInfo;
|
|
if (rawDragInfo instanceof ShortcutInfo) {
|
|
ShortcutInfo dragInfo = (ShortcutInfo) rawDragInfo;
|
|
for (ApplicationInfo info : apps) {
|
|
if (dragInfo.intent.getComponent().equals(info.intent.getComponent())) {
|
|
cancelDrag();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void endDrag() {
|
|
if (mDragging) {
|
|
mDragging = false;
|
|
for (DragListener listener : mListeners) {
|
|
listener.onDragEnd();
|
|
}
|
|
if (mDragObject.dragView != null) {
|
|
mDragObject.dragView.remove();
|
|
mDragObject.dragView = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clamps the position to the drag layer bounds.
|
|
*/
|
|
private int[] getClampedDragLayerPos(float x, float y) {
|
|
mLauncher.getDragLayer().getLocalVisibleRect(mDragLayerRect);
|
|
mTmpPoint[0] = (int) Math.max(mDragLayerRect.left, Math.min(x, mDragLayerRect.right - 1));
|
|
mTmpPoint[1] = (int) Math.max(mDragLayerRect.top, Math.min(y, mDragLayerRect.bottom - 1));
|
|
return mTmpPoint;
|
|
}
|
|
|
|
/**
|
|
* Call this from a drag source view.
|
|
*/
|
|
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
|
if (false) {
|
|
Log.d(Launcher.TAG, "DragController.onInterceptTouchEvent " + ev + " mDragging="
|
|
+ mDragging);
|
|
}
|
|
final int action = ev.getAction();
|
|
|
|
final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
|
|
final int dragLayerX = dragLayerPos[0];
|
|
final int dragLayerY = dragLayerPos[1];
|
|
|
|
switch (action) {
|
|
case MotionEvent.ACTION_MOVE:
|
|
break;
|
|
case MotionEvent.ACTION_DOWN:
|
|
// Remember location of down touch
|
|
mMotionDownX = dragLayerX;
|
|
mMotionDownY = dragLayerY;
|
|
mLastDropTarget = null;
|
|
break;
|
|
case MotionEvent.ACTION_UP:
|
|
if (mDragging) {
|
|
drop(dragLayerX, dragLayerY);
|
|
}
|
|
endDrag();
|
|
break;
|
|
case MotionEvent.ACTION_CANCEL:
|
|
cancelDrag();
|
|
break;
|
|
}
|
|
|
|
return mDragging;
|
|
}
|
|
|
|
/**
|
|
* Sets the view that should handle move events.
|
|
*/
|
|
void setMoveTarget(View view) {
|
|
mMoveTarget = view;
|
|
}
|
|
|
|
public boolean dispatchUnhandledMove(View focused, int direction) {
|
|
return mMoveTarget != null && mMoveTarget.dispatchUnhandledMove(focused, direction);
|
|
}
|
|
|
|
private void handleMoveEvent(int x, int y) {
|
|
mDragObject.dragView.move(x, y);
|
|
|
|
// Drop on someone?
|
|
final int[] coordinates = mCoordinatesTemp;
|
|
DropTarget dropTarget = findDropTarget(x, y, coordinates);
|
|
mDragObject.x = coordinates[0];
|
|
mDragObject.y = coordinates[1];
|
|
if (dropTarget != null) {
|
|
DropTarget delegate = dropTarget.getDropTargetDelegate(mDragObject);
|
|
if (delegate != null) {
|
|
dropTarget = delegate;
|
|
}
|
|
|
|
if (mLastDropTarget != dropTarget) {
|
|
if (mLastDropTarget != null) {
|
|
mLastDropTarget.onDragExit(mDragObject);
|
|
}
|
|
dropTarget.onDragEnter(mDragObject);
|
|
}
|
|
dropTarget.onDragOver(mDragObject);
|
|
} else {
|
|
if (mLastDropTarget != null) {
|
|
mLastDropTarget.onDragExit(mDragObject);
|
|
}
|
|
}
|
|
mLastDropTarget = dropTarget;
|
|
|
|
// Scroll, maybe, but not if we're in the delete region.
|
|
boolean inDeleteRegion = false;
|
|
if (mDeleteRegion != null) {
|
|
inDeleteRegion = mDeleteRegion.contains(x, y);
|
|
}
|
|
|
|
// After a scroll, the touch point will still be in the scroll region.
|
|
// Rather than scrolling immediately, require a bit of twiddling to scroll again
|
|
final int slop = ViewConfiguration.get(mLauncher).getScaledWindowTouchSlop();
|
|
mDistanceSinceScroll +=
|
|
Math.sqrt(Math.pow(mLastTouch[0] - x, 2) + Math.pow(mLastTouch[1] - y, 2));
|
|
mLastTouch[0] = x;
|
|
mLastTouch[1] = y;
|
|
|
|
if (!inDeleteRegion && x < mScrollZone) {
|
|
if (mScrollState == SCROLL_OUTSIDE_ZONE && mDistanceSinceScroll > slop) {
|
|
mScrollState = SCROLL_WAITING_IN_ZONE;
|
|
if (mDragScroller.onEnterScrollArea(x, y, SCROLL_LEFT)) {
|
|
mScrollRunnable.setDirection(SCROLL_LEFT);
|
|
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
|
|
}
|
|
}
|
|
} else if (!inDeleteRegion && x > mScrollView.getWidth() - mScrollZone) {
|
|
if (mScrollState == SCROLL_OUTSIDE_ZONE && mDistanceSinceScroll > slop) {
|
|
mScrollState = SCROLL_WAITING_IN_ZONE;
|
|
if (mDragScroller.onEnterScrollArea(x, y, SCROLL_RIGHT)) {
|
|
mScrollRunnable.setDirection(SCROLL_RIGHT);
|
|
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
|
|
}
|
|
}
|
|
} else {
|
|
if (mScrollState == SCROLL_WAITING_IN_ZONE) {
|
|
mScrollState = SCROLL_OUTSIDE_ZONE;
|
|
mScrollRunnable.setDirection(SCROLL_RIGHT);
|
|
mHandler.removeCallbacks(mScrollRunnable);
|
|
mDragScroller.onExitScrollArea();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call this from a drag source view.
|
|
*/
|
|
public boolean onTouchEvent(MotionEvent ev) {
|
|
if (!mDragging) {
|
|
return false;
|
|
}
|
|
|
|
final int action = ev.getAction();
|
|
final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
|
|
final int dragLayerX = dragLayerPos[0];
|
|
final int dragLayerY = dragLayerPos[1];
|
|
|
|
switch (action) {
|
|
case MotionEvent.ACTION_DOWN:
|
|
// Remember where the motion event started
|
|
mMotionDownX = dragLayerX;
|
|
mMotionDownY = dragLayerY;
|
|
|
|
if ((dragLayerX < mScrollZone) || (dragLayerX > mScrollView.getWidth() - mScrollZone)) {
|
|
mScrollState = SCROLL_WAITING_IN_ZONE;
|
|
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
|
|
} else {
|
|
mScrollState = SCROLL_OUTSIDE_ZONE;
|
|
}
|
|
break;
|
|
case MotionEvent.ACTION_MOVE:
|
|
handleMoveEvent(dragLayerX, dragLayerY);
|
|
break;
|
|
case MotionEvent.ACTION_UP:
|
|
// Ensure that we've processed a move event at the current pointer location.
|
|
handleMoveEvent(dragLayerX, dragLayerY);
|
|
|
|
mHandler.removeCallbacks(mScrollRunnable);
|
|
if (mDragging) {
|
|
drop(dragLayerX, dragLayerY);
|
|
}
|
|
endDrag();
|
|
break;
|
|
case MotionEvent.ACTION_CANCEL:
|
|
cancelDrag();
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private void drop(float x, float y) {
|
|
final int[] coordinates = mCoordinatesTemp;
|
|
final DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);
|
|
|
|
mDragObject.x = coordinates[0];
|
|
mDragObject.y = coordinates[1];
|
|
boolean accepted = false;
|
|
if (dropTarget != null) {
|
|
mDragObject.dragComplete = true;
|
|
dropTarget.onDragExit(mDragObject);
|
|
if (dropTarget.acceptDrop(mDragObject)) {
|
|
dropTarget.onDrop(mDragObject);
|
|
accepted = true;
|
|
}
|
|
}
|
|
mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject, accepted);
|
|
}
|
|
|
|
private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
|
|
final Rect r = mRectTemp;
|
|
|
|
final ArrayList<DropTarget> dropTargets = mDropTargets;
|
|
final int count = dropTargets.size();
|
|
for (int i=count-1; i>=0; i--) {
|
|
DropTarget target = dropTargets.get(i);
|
|
if (!target.isDropEnabled())
|
|
continue;
|
|
|
|
target.getHitRect(r);
|
|
|
|
// Convert the hit rect to DragLayer coordinates
|
|
target.getLocationInDragLayer(dropCoordinates);
|
|
r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop());
|
|
|
|
mDragObject.x = x;
|
|
mDragObject.y = y;
|
|
if (r.contains(x, y)) {
|
|
DropTarget delegate = target.getDropTargetDelegate(mDragObject);
|
|
if (delegate != null) {
|
|
target = delegate;
|
|
target.getLocationInDragLayer(dropCoordinates);
|
|
}
|
|
|
|
// Make dropCoordinates relative to the DropTarget
|
|
dropCoordinates[0] = x - dropCoordinates[0];
|
|
dropCoordinates[1] = y - dropCoordinates[1];
|
|
|
|
return target;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void setDragScoller(DragScroller scroller) {
|
|
mDragScroller = scroller;
|
|
}
|
|
|
|
public void setWindowToken(IBinder token) {
|
|
mWindowToken = token;
|
|
}
|
|
|
|
/**
|
|
* Sets the drag listner which will be notified when a drag starts or ends.
|
|
*/
|
|
public void addDragListener(DragListener l) {
|
|
mListeners.add(l);
|
|
}
|
|
|
|
/**
|
|
* Remove a previously installed drag listener.
|
|
*/
|
|
public void removeDragListener(DragListener l) {
|
|
mListeners.remove(l);
|
|
}
|
|
|
|
/**
|
|
* Add a DropTarget to the list of potential places to receive drop events.
|
|
*/
|
|
public void addDropTarget(DropTarget target) {
|
|
mDropTargets.add(target);
|
|
}
|
|
|
|
/**
|
|
* Don't send drop events to <em>target</em> any more.
|
|
*/
|
|
public void removeDropTarget(DropTarget target) {
|
|
mDropTargets.remove(target);
|
|
}
|
|
|
|
/**
|
|
* Set which view scrolls for touch events near the edge of the screen.
|
|
*/
|
|
public void setScrollView(View v) {
|
|
mScrollView = v;
|
|
}
|
|
|
|
/**
|
|
* Specifies the delete region. We won't scroll on touch events over the delete region.
|
|
*
|
|
* @param region The rectangle in DragLayer coordinates of the delete region.
|
|
*/
|
|
void setDeleteRegion(RectF region) {
|
|
mDeleteRegion = region;
|
|
}
|
|
|
|
DragView getDragView() {
|
|
return mDragObject.dragView;
|
|
}
|
|
|
|
private class ScrollRunnable implements Runnable {
|
|
private int mDirection;
|
|
|
|
ScrollRunnable() {
|
|
}
|
|
|
|
public void run() {
|
|
if (mDragScroller != null) {
|
|
if (mDirection == SCROLL_LEFT) {
|
|
mDragScroller.scrollLeft();
|
|
} else {
|
|
mDragScroller.scrollRight();
|
|
}
|
|
mScrollState = SCROLL_OUTSIDE_ZONE;
|
|
mDistanceSinceScroll = 0;
|
|
mDragScroller.onExitScrollArea();
|
|
}
|
|
}
|
|
|
|
void setDirection(int direction) {
|
|
mDirection = direction;
|
|
}
|
|
}
|
|
}
|