Now that touch events can go off the edge of the screen, clamp

them to the screen size for hit testing purposes while dragging.
This commit is contained in:
Joe Onorato
2009-09-25 10:39:17 -07:00
parent 7bb1749c69
commit e048e8a8ef
+43 -14
View File
@@ -27,11 +27,13 @@ import android.os.Handler;
import android.os.Vibrator; import android.os.Vibrator;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
@@ -77,6 +79,9 @@ public class DragController {
/** Y coordinate of the down event. */ /** Y coordinate of the down event. */
private float mMotionDownY; private float mMotionDownY;
/** Info about the screen for clamping. */
private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
/** Original view that is being dragged. */ /** Original view that is being dragged. */
private View mOriginator; private View mOriginator;
@@ -298,8 +303,8 @@ public class DragController {
} }
final int action = ev.getAction(); final int action = ev.getAction();
final float screenX = ev.getRawX(); final int screenX = clamp((int)ev.getRawX(), 0, mDisplayMetrics.widthPixels);
final float screenY = ev.getRawY(); final int screenY = clamp((int)ev.getRawY(), 0, mDisplayMetrics.heightPixels);
switch (action) { switch (action) {
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
@@ -309,6 +314,7 @@ public class DragController {
// Remember location of down touch // Remember location of down touch
mMotionDownX = screenX; mMotionDownX = screenX;
mMotionDownY = screenY; mMotionDownY = screenY;
recordScreenSize();
mLastDropTarget = null; mLastDropTarget = null;
break; break;
@@ -335,17 +341,17 @@ public class DragController {
} }
final int action = ev.getAction(); final int action = ev.getAction();
final float x = ev.getRawX(); final int screenX = clamp((int)ev.getRawX(), 0, mDisplayMetrics.widthPixels);
final float y = ev.getRawY(); final int screenY = clamp((int)ev.getRawY(), 0, mDisplayMetrics.heightPixels);
switch (action) { switch (action) {
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
// Remember where the motion event started // Remember where the motion event started
mMotionDownX = x; mMotionDownX = screenX;
mMotionDownY = y; mMotionDownY = screenY;
recordScreenSize();
if ((x < SCROLL_ZONE) || (x > scrollView.getWidth() - SCROLL_ZONE)) { if ((screenX < SCROLL_ZONE) || (screenX > scrollView.getWidth() - SCROLL_ZONE)) {
mScrollState = SCROLL_WAITING_IN_ZONE; mScrollState = SCROLL_WAITING_IN_ZONE;
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY); mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
} else { } else {
@@ -354,12 +360,13 @@ public class DragController {
break; break;
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
// Update the drag view. // Update the drag view. Don't use the clamped pos here so the dragging looks
// like it goes off screen a little, intead of bumping up against the edge.
mDragView.move((int)ev.getRawX(), (int)ev.getRawY()); mDragView.move((int)ev.getRawX(), (int)ev.getRawY());
// Drop on someone? // Drop on someone?
final int[] coordinates = mCoordinatesTemp; final int[] coordinates = mCoordinatesTemp;
DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates); DropTarget dropTarget = findDropTarget((int) screenX, (int) screenY, coordinates);
if (dropTarget != null) { if (dropTarget != null) {
if (mLastDropTarget == dropTarget) { if (mLastDropTarget == dropTarget) {
dropTarget.onDragOver(mDragSource, coordinates[0], coordinates[1], dropTarget.onDragOver(mDragSource, coordinates[0], coordinates[1],
@@ -383,15 +390,15 @@ public class DragController {
// Scroll, maybe, but not if we're in the delete region. // Scroll, maybe, but not if we're in the delete region.
boolean inDeleteRegion = false; boolean inDeleteRegion = false;
if (mDeleteRegion != null) { if (mDeleteRegion != null) {
inDeleteRegion = mDeleteRegion.contains(ev.getRawX(), ev.getRawY()); inDeleteRegion = mDeleteRegion.contains(screenX, screenY);
} }
if (!inDeleteRegion && x < SCROLL_ZONE) { if (!inDeleteRegion && screenX < SCROLL_ZONE) {
if (mScrollState == SCROLL_OUTSIDE_ZONE) { if (mScrollState == SCROLL_OUTSIDE_ZONE) {
mScrollState = SCROLL_WAITING_IN_ZONE; mScrollState = SCROLL_WAITING_IN_ZONE;
mScrollRunnable.setDirection(SCROLL_LEFT); mScrollRunnable.setDirection(SCROLL_LEFT);
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY); mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
} }
} else if (!inDeleteRegion && x > scrollView.getWidth() - SCROLL_ZONE) { } else if (!inDeleteRegion && screenX > scrollView.getWidth() - SCROLL_ZONE) {
if (mScrollState == SCROLL_OUTSIDE_ZONE) { if (mScrollState == SCROLL_OUTSIDE_ZONE) {
mScrollState = SCROLL_WAITING_IN_ZONE; mScrollState = SCROLL_WAITING_IN_ZONE;
mScrollRunnable.setDirection(SCROLL_RIGHT); mScrollRunnable.setDirection(SCROLL_RIGHT);
@@ -409,7 +416,7 @@ public class DragController {
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
mHandler.removeCallbacks(mScrollRunnable); mHandler.removeCallbacks(mScrollRunnable);
if (mDragging) { if (mDragging) {
drop(x, y); drop(screenX, screenY);
} }
endDrag(); endDrag();
@@ -461,6 +468,28 @@ public class DragController {
return null; return null;
} }
/**
* Get the screen size so we can clamp events to the screen size so even if
* you drag off the edge of the screen, we find something.
*/
private void recordScreenSize() {
((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay().getMetrics(mDisplayMetrics);
}
/**
* Clamp val to be &gt;= min and &lt; max.
*/
private static int clamp(int val, int min, int max) {
if (val < min) {
return min;
} else if (val >= max) {
return max - 1;
} else {
return val;
}
}
public void setDragScoller(DragScroller scroller) { public void setDragScoller(DragScroller scroller) {
mDragScroller = scroller; mDragScroller = scroller;
} }