Skip to content

Commit 3dda2cf

Browse files
adampAndroid Git Automerger
authored andcommitted
am ecb388e: Merge "DO NOT MERGE - Use focal point for scrolling in GestureDetector" into jb-dev
* commit 'ecb388efefc427c3fa93f07fd11502564dc194a5': DO NOT MERGE - Use focal point for scrolling in GestureDetector
2 parents 00925a3 + ecb388e commit 3dda2cf

File tree

1 file changed

+64
-54
lines changed

1 file changed

+64
-54
lines changed

core/java/android/view/GestureDetector.java

Lines changed: 64 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -226,17 +226,12 @@ public boolean onSingleTapConfirmed(MotionEvent e) {
226226
*/
227227
private boolean mIsDoubleTapping;
228228

229-
private float mLastMotionY;
230-
private float mLastMotionX;
229+
private float mLastFocusX;
230+
private float mLastFocusY;
231+
private float mDownFocusX;
232+
private float mDownFocusY;
231233

232234
private boolean mIsLongpressEnabled;
233-
234-
/**
235-
* True if we are at a target API level of >= Froyo or the developer can
236-
* explicitly set it. If true, input events with > 1 pointer will be ignored
237-
* so we can work side by side with multitouch gesture detectors.
238-
*/
239-
private boolean mIgnoreMultitouch;
240235

241236
/**
242237
* Determines speed during touch scrolling
@@ -349,8 +344,16 @@ public GestureDetector(Context context, OnGestureListener listener) {
349344
* @throws NullPointerException if {@code listener} is null.
350345
*/
351346
public GestureDetector(Context context, OnGestureListener listener, Handler handler) {
352-
this(context, listener, handler, context != null &&
353-
context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.FROYO);
347+
if (handler != null) {
348+
mHandler = new GestureHandler(handler);
349+
} else {
350+
mHandler = new GestureHandler();
351+
}
352+
mListener = listener;
353+
if (listener instanceof OnDoubleTapListener) {
354+
setOnDoubleTapListener((OnDoubleTapListener) listener);
355+
}
356+
init(context);
354357
}
355358

356359
/**
@@ -362,31 +365,19 @@ public GestureDetector(Context context, OnGestureListener listener, Handler hand
362365
* @param listener the listener invoked for all the callbacks, this must
363366
* not be null.
364367
* @param handler the handler to use
365-
* @param ignoreMultitouch whether events involving more than one pointer should
366-
* be ignored.
367368
*
368369
* @throws NullPointerException if {@code listener} is null.
369370
*/
370371
public GestureDetector(Context context, OnGestureListener listener, Handler handler,
371-
boolean ignoreMultitouch) {
372-
if (handler != null) {
373-
mHandler = new GestureHandler(handler);
374-
} else {
375-
mHandler = new GestureHandler();
376-
}
377-
mListener = listener;
378-
if (listener instanceof OnDoubleTapListener) {
379-
setOnDoubleTapListener((OnDoubleTapListener) listener);
380-
}
381-
init(context, ignoreMultitouch);
372+
boolean unused) {
373+
this(context, listener, handler);
382374
}
383375

384-
private void init(Context context, boolean ignoreMultitouch) {
376+
private void init(Context context) {
385377
if (mListener == null) {
386378
throw new NullPointerException("OnGestureListener must not be null");
387379
}
388380
mIsLongpressEnabled = true;
389-
mIgnoreMultitouch = ignoreMultitouch;
390381

391382
// Fallback to support pre-donuts releases
392383
int touchSlop, doubleTapSlop, doubleTapTouchSlop;
@@ -456,34 +447,40 @@ public boolean onTouchEvent(MotionEvent ev) {
456447
}
457448

458449
final int action = ev.getAction();
459-
final float y = ev.getY();
460-
final float x = ev.getX();
461450

462451
if (mVelocityTracker == null) {
463452
mVelocityTracker = VelocityTracker.obtain();
464453
}
465454
mVelocityTracker.addMovement(ev);
466455

456+
final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP;
457+
final int skipIndex = pointerUp ? ev.getActionIndex() : -1;
458+
459+
// Determine focal point
460+
float sumX = 0, sumY = 0;
461+
final int count = ev.getPointerCount();
462+
for (int i = 0; i < count; i++) {
463+
if (skipIndex == i) continue;
464+
sumX += ev.getX(i);
465+
sumY += ev.getY(i);
466+
}
467+
final int div = pointerUp ? count - 1 : count;
468+
final float focusX = sumX / div;
469+
final float focusY = sumY / div;
470+
467471
boolean handled = false;
468472

469473
switch (action & MotionEvent.ACTION_MASK) {
470474
case MotionEvent.ACTION_POINTER_DOWN:
471-
if (mIgnoreMultitouch) {
472-
// Multitouch event - abort.
473-
cancel();
474-
}
475+
mDownFocusX = mLastFocusX = focusX;
476+
mDownFocusY = mLastFocusY = focusY;
477+
// Cancel long press and taps
478+
cancelTaps();
475479
break;
476480

477481
case MotionEvent.ACTION_POINTER_UP:
478-
// Ending a multitouch gesture and going back to 1 finger
479-
if (mIgnoreMultitouch && ev.getPointerCount() == 2) {
480-
int index = (((action & MotionEvent.ACTION_POINTER_INDEX_MASK)
481-
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT) == 0) ? 1 : 0;
482-
mLastMotionX = ev.getX(index);
483-
mLastMotionY = ev.getY(index);
484-
mVelocityTracker.recycle();
485-
mVelocityTracker = VelocityTracker.obtain();
486-
}
482+
mDownFocusX = mLastFocusX = focusX;
483+
mDownFocusY = mLastFocusY = focusY;
487484
break;
488485

489486
case MotionEvent.ACTION_DOWN:
@@ -504,8 +501,8 @@ public boolean onTouchEvent(MotionEvent ev) {
504501
}
505502
}
506503

507-
mLastMotionX = x;
508-
mLastMotionY = y;
504+
mDownFocusX = mLastFocusX = focusX;
505+
mDownFocusY = mLastFocusY = focusY;
509506
if (mCurrentDownEvent != null) {
510507
mCurrentDownEvent.recycle();
511508
}
@@ -525,22 +522,22 @@ public boolean onTouchEvent(MotionEvent ev) {
525522
break;
526523

527524
case MotionEvent.ACTION_MOVE:
528-
if (mInLongPress || (mIgnoreMultitouch && ev.getPointerCount() > 1)) {
525+
if (mInLongPress) {
529526
break;
530527
}
531-
final float scrollX = mLastMotionX - x;
532-
final float scrollY = mLastMotionY - y;
528+
final float scrollX = mLastFocusX - focusX;
529+
final float scrollY = mLastFocusY - focusY;
533530
if (mIsDoubleTapping) {
534531
// Give the move events of the double-tap
535532
handled |= mDoubleTapListener.onDoubleTapEvent(ev);
536533
} else if (mAlwaysInTapRegion) {
537-
final int deltaX = (int) (x - mCurrentDownEvent.getX());
538-
final int deltaY = (int) (y - mCurrentDownEvent.getY());
534+
final int deltaX = (int) (focusX - mDownFocusX);
535+
final int deltaY = (int) (focusY - mDownFocusY);
539536
int distance = (deltaX * deltaX) + (deltaY * deltaY);
540537
if (distance > mTouchSlopSquare) {
541538
handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
542-
mLastMotionX = x;
543-
mLastMotionY = y;
539+
mLastFocusX = focusX;
540+
mLastFocusY = focusY;
544541
mAlwaysInTapRegion = false;
545542
mHandler.removeMessages(TAP);
546543
mHandler.removeMessages(SHOW_PRESS);
@@ -551,8 +548,8 @@ public boolean onTouchEvent(MotionEvent ev) {
551548
}
552549
} else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) {
553550
handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
554-
mLastMotionX = x;
555-
mLastMotionY = y;
551+
mLastFocusX = focusX;
552+
mLastFocusY = focusY;
556553
}
557554
break;
558555

@@ -571,9 +568,10 @@ public boolean onTouchEvent(MotionEvent ev) {
571568

572569
// A fling must travel the minimum tap distance
573570
final VelocityTracker velocityTracker = mVelocityTracker;
571+
final int pointerId = ev.getPointerId(0);
574572
velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
575-
final float velocityY = velocityTracker.getYVelocity();
576-
final float velocityX = velocityTracker.getXVelocity();
573+
final float velocityY = velocityTracker.getYVelocity(pointerId);
574+
final float velocityX = velocityTracker.getXVelocity(pointerId);
577575

578576
if ((Math.abs(velocityY) > mMinimumFlingVelocity)
579577
|| (Math.abs(velocityX) > mMinimumFlingVelocity)){
@@ -622,6 +620,18 @@ private void cancel() {
622620
}
623621
}
624622

623+
private void cancelTaps() {
624+
mHandler.removeMessages(SHOW_PRESS);
625+
mHandler.removeMessages(LONG_PRESS);
626+
mHandler.removeMessages(TAP);
627+
mIsDoubleTapping = false;
628+
mAlwaysInTapRegion = false;
629+
mAlwaysInBiggerTapRegion = false;
630+
if (mInLongPress) {
631+
mInLongPress = false;
632+
}
633+
}
634+
625635
private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp,
626636
MotionEvent secondDown) {
627637
if (!mAlwaysInBiggerTapRegion) {

0 commit comments

Comments
 (0)