Merge "Edge of screen slop detection for ScaleGestureDetector." into eclair

This commit is contained in:
Adam Powell
2010-01-19 16:40:17 -08:00
committed by Android (Google) Code Review

View File

@@ -17,6 +17,8 @@
package android.view; package android.view;
import android.content.Context; import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log;
/** /**
* Detects transformation gestures involving more than one pointer ("multitouch") * Detects transformation gestures involving more than one pointer ("multitouch")
@@ -137,10 +139,20 @@ public class ScaleGestureDetector {
private float mCurrPressure; private float mCurrPressure;
private float mPrevPressure; private float mPrevPressure;
private long mTimeDelta; private long mTimeDelta;
private float mEdgeSlop;
private float mRightSlopEdge;
private float mBottomSlopEdge;
private boolean mSloppyGesture;
public ScaleGestureDetector(Context context, OnScaleGestureListener listener) { public ScaleGestureDetector(Context context, OnScaleGestureListener listener) {
ViewConfiguration config = ViewConfiguration.get(context);
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
mContext = context; mContext = context;
mListener = listener; mListener = listener;
mEdgeSlop = config.getScaledEdgeSlop();
mRightSlopEdge = metrics.widthPixels - mEdgeSlop;
mBottomSlopEdge = metrics.heightPixels - mEdgeSlop;
} }
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
@@ -152,15 +164,68 @@ public class ScaleGestureDetector {
action == MotionEvent.ACTION_POINTER_2_DOWN) && action == MotionEvent.ACTION_POINTER_2_DOWN) &&
event.getPointerCount() >= 2) { event.getPointerCount() >= 2) {
// We have a new multi-finger gesture // We have a new multi-finger gesture
// Be paranoid in case we missed an event // Be paranoid in case we missed an event
reset(); reset();
mPrevEvent = MotionEvent.obtain(event); mPrevEvent = MotionEvent.obtain(event);
mTimeDelta = 0; mTimeDelta = 0;
setContext(event); setContext(event);
mGestureInProgress = mListener.onScaleBegin(this);
// Check if we have a sloppy gesture. If so, delay
// the beginning of the gesture until we're sure that's
// what the user wanted. Sloppy gestures can happen if the
// edge of the user's hand is touching the screen, for example.
final float edgeSlop = mEdgeSlop;
final float rightSlop = mRightSlopEdge;
final float bottomSlop = mBottomSlopEdge;
final float x0 = event.getRawX();
final float y0 = event.getRawY();
final float x1 = getRawX(event, 1);
final float y1 = getRawY(event, 1);
boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop ||
x1 < edgeSlop || y1 < edgeSlop;
boolean p1sloppy = x0 > rightSlop || y0 > bottomSlop ||
x1 > rightSlop || y1 > bottomSlop;
if (p0sloppy) {
mFocusX = event.getX(1);
mFocusY = event.getY(1);
mSloppyGesture = true;
} else if (p1sloppy) {
mFocusX = event.getX(0);
mFocusY = event.getY(0);
mSloppyGesture = true;
} else {
mGestureInProgress = mListener.onScaleBegin(this);
}
} else if (action == MotionEvent.ACTION_MOVE && mSloppyGesture) {
// Initiate sloppy gestures if we've moved outside of the slop area.
final float edgeSlop = mEdgeSlop;
final float rightSlop = mRightSlopEdge;
final float bottomSlop = mBottomSlopEdge;
final float x0 = event.getRawX();
final float y0 = event.getRawY();
final float x1 = getRawX(event, 1);
final float y1 = getRawY(event, 1);
boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop ||
x1 < edgeSlop || y1 < edgeSlop;
boolean p1sloppy = x0 > rightSlop || y0 > bottomSlop ||
x1 > rightSlop || y1 > bottomSlop;
if (p0sloppy) {
mFocusX = event.getX(1);
mFocusY = event.getY(1);
} else if (p1sloppy) {
mFocusX = event.getX(0);
mFocusY = event.getY(0);
} else {
mSloppyGesture = false;
mGestureInProgress = mListener.onScaleBegin(this);
}
} }
} else { } else {
// Transform gesture in progress - attempt to handle it // Transform gesture in progress - attempt to handle it
@@ -169,22 +234,24 @@ public class ScaleGestureDetector {
case MotionEvent.ACTION_POINTER_2_UP: case MotionEvent.ACTION_POINTER_2_UP:
// Gesture ended // Gesture ended
setContext(event); setContext(event);
// Set focus point to the remaining finger // Set focus point to the remaining finger
int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK) int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK)
>> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0; >> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0;
mFocusX = event.getX(id); mFocusX = event.getX(id);
mFocusY = event.getY(id); mFocusY = event.getY(id);
mListener.onScaleEnd(this); if (!mSloppyGesture) {
mGestureInProgress = false; mListener.onScaleEnd(this);
}
reset(); reset();
break; break;
case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_CANCEL:
mListener.onScaleEnd(this); if (!mSloppyGesture) {
mGestureInProgress = false; mListener.onScaleEnd(this);
}
reset(); reset();
break; break;
@@ -208,6 +275,22 @@ public class ScaleGestureDetector {
} }
return handled; return handled;
} }
/**
* MotionEvent has no getRawX(int) method; simulate it pending future API approval.
*/
private static float getRawX(MotionEvent event, int pointerIndex) {
float offset = event.getX() - event.getRawX();
return event.getX(pointerIndex) + offset;
}
/**
* MotionEvent has no getRawY(int) method; simulate it pending future API approval.
*/
private static float getRawY(MotionEvent event, int pointerIndex) {
float offset = event.getY() - event.getRawY();
return event.getY(pointerIndex) + offset;
}
private void setContext(MotionEvent curr) { private void setContext(MotionEvent curr) {
if (mCurrEvent != null) { if (mCurrEvent != null) {
@@ -255,6 +338,8 @@ public class ScaleGestureDetector {
mCurrEvent.recycle(); mCurrEvent.recycle();
mCurrEvent = null; mCurrEvent = null;
} }
mSloppyGesture = false;
mGestureInProgress = false;
} }
/** /**