422 lines
20 KiB
Java
422 lines
20 KiB
Java
package androidx.core.view;
|
|
|
|
import android.content.Context;
|
|
import android.os.Handler;
|
|
import android.os.Message;
|
|
import android.view.GestureDetector;
|
|
import android.view.MotionEvent;
|
|
import android.view.VelocityTracker;
|
|
import android.view.ViewConfiguration;
|
|
public final class GestureDetectorCompat {
|
|
private final GestureDetectorCompatImpl mImpl;
|
|
|
|
public interface GestureDetectorCompatImpl {
|
|
boolean isLongpressEnabled();
|
|
|
|
boolean onTouchEvent(MotionEvent motionEvent);
|
|
|
|
void setIsLongpressEnabled(boolean z2);
|
|
|
|
void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener);
|
|
}
|
|
|
|
public static class GestureDetectorCompatImplBase implements GestureDetectorCompatImpl {
|
|
private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
|
|
private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout();
|
|
private static final int LONG_PRESS = 2;
|
|
private static final int SHOW_PRESS = 1;
|
|
private static final int TAP = 3;
|
|
private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout();
|
|
private boolean mAlwaysInBiggerTapRegion;
|
|
private boolean mAlwaysInTapRegion;
|
|
public MotionEvent mCurrentDownEvent;
|
|
public boolean mDeferConfirmSingleTap;
|
|
public GestureDetector.OnDoubleTapListener mDoubleTapListener;
|
|
private int mDoubleTapSlopSquare;
|
|
private float mDownFocusX;
|
|
private float mDownFocusY;
|
|
private final Handler mHandler;
|
|
private boolean mInLongPress;
|
|
private boolean mIsDoubleTapping;
|
|
private boolean mIsLongpressEnabled;
|
|
private float mLastFocusX;
|
|
private float mLastFocusY;
|
|
public final GestureDetector.OnGestureListener mListener;
|
|
private int mMaximumFlingVelocity;
|
|
private int mMinimumFlingVelocity;
|
|
private MotionEvent mPreviousUpEvent;
|
|
public boolean mStillDown;
|
|
private int mTouchSlopSquare;
|
|
private VelocityTracker mVelocityTracker;
|
|
|
|
public class GestureHandler extends Handler {
|
|
public GestureHandler() {
|
|
}
|
|
|
|
public GestureHandler(Handler handler) {
|
|
super(handler.getLooper());
|
|
}
|
|
|
|
@Override // android.os.Handler
|
|
public void handleMessage(Message message) {
|
|
int i = message.what;
|
|
if (i == 1) {
|
|
GestureDetectorCompatImplBase gestureDetectorCompatImplBase = GestureDetectorCompatImplBase.this;
|
|
gestureDetectorCompatImplBase.mListener.onShowPress(gestureDetectorCompatImplBase.mCurrentDownEvent);
|
|
} else if (i == 2) {
|
|
GestureDetectorCompatImplBase.this.dispatchLongPress();
|
|
} else if (i == 3) {
|
|
GestureDetectorCompatImplBase gestureDetectorCompatImplBase2 = GestureDetectorCompatImplBase.this;
|
|
GestureDetector.OnDoubleTapListener onDoubleTapListener = gestureDetectorCompatImplBase2.mDoubleTapListener;
|
|
if (onDoubleTapListener == null) {
|
|
return;
|
|
}
|
|
if (!gestureDetectorCompatImplBase2.mStillDown) {
|
|
onDoubleTapListener.onSingleTapConfirmed(gestureDetectorCompatImplBase2.mCurrentDownEvent);
|
|
} else {
|
|
gestureDetectorCompatImplBase2.mDeferConfirmSingleTap = true;
|
|
}
|
|
} else {
|
|
throw new RuntimeException("Unknown message " + message);
|
|
}
|
|
}
|
|
}
|
|
|
|
public GestureDetectorCompatImplBase(Context context, GestureDetector.OnGestureListener onGestureListener, Handler handler) {
|
|
if (handler != null) {
|
|
this.mHandler = new GestureHandler(handler);
|
|
} else {
|
|
this.mHandler = new GestureHandler();
|
|
}
|
|
this.mListener = onGestureListener;
|
|
if (onGestureListener instanceof GestureDetector.OnDoubleTapListener) {
|
|
setOnDoubleTapListener((GestureDetector.OnDoubleTapListener) onGestureListener);
|
|
}
|
|
init(context);
|
|
}
|
|
|
|
private void cancel() {
|
|
this.mHandler.removeMessages(1);
|
|
this.mHandler.removeMessages(2);
|
|
this.mHandler.removeMessages(3);
|
|
this.mVelocityTracker.recycle();
|
|
this.mVelocityTracker = null;
|
|
this.mIsDoubleTapping = false;
|
|
this.mStillDown = false;
|
|
this.mAlwaysInTapRegion = false;
|
|
this.mAlwaysInBiggerTapRegion = false;
|
|
this.mDeferConfirmSingleTap = false;
|
|
if (this.mInLongPress) {
|
|
this.mInLongPress = false;
|
|
}
|
|
}
|
|
|
|
private void cancelTaps() {
|
|
this.mHandler.removeMessages(1);
|
|
this.mHandler.removeMessages(2);
|
|
this.mHandler.removeMessages(3);
|
|
this.mIsDoubleTapping = false;
|
|
this.mAlwaysInTapRegion = false;
|
|
this.mAlwaysInBiggerTapRegion = false;
|
|
this.mDeferConfirmSingleTap = false;
|
|
if (this.mInLongPress) {
|
|
this.mInLongPress = false;
|
|
}
|
|
}
|
|
|
|
private void init(Context context) {
|
|
if (context == null) {
|
|
throw new IllegalArgumentException("Context must not be null");
|
|
} else if (this.mListener != null) {
|
|
this.mIsLongpressEnabled = true;
|
|
ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
|
|
int scaledTouchSlop = viewConfiguration.getScaledTouchSlop();
|
|
int scaledDoubleTapSlop = viewConfiguration.getScaledDoubleTapSlop();
|
|
this.mMinimumFlingVelocity = viewConfiguration.getScaledMinimumFlingVelocity();
|
|
this.mMaximumFlingVelocity = viewConfiguration.getScaledMaximumFlingVelocity();
|
|
this.mTouchSlopSquare = scaledTouchSlop * scaledTouchSlop;
|
|
this.mDoubleTapSlopSquare = scaledDoubleTapSlop * scaledDoubleTapSlop;
|
|
} else {
|
|
throw new IllegalArgumentException("OnGestureListener must not be null");
|
|
}
|
|
}
|
|
|
|
private boolean isConsideredDoubleTap(MotionEvent motionEvent, MotionEvent motionEvent2, MotionEvent motionEvent3) {
|
|
if (!this.mAlwaysInBiggerTapRegion || motionEvent3.getEventTime() - motionEvent2.getEventTime() > ((long) DOUBLE_TAP_TIMEOUT)) {
|
|
return false;
|
|
}
|
|
int x2 = ((int) motionEvent.getX()) - ((int) motionEvent3.getX());
|
|
int y2 = ((int) motionEvent.getY()) - ((int) motionEvent3.getY());
|
|
return (y2 * y2) + (x2 * x2) < this.mDoubleTapSlopSquare;
|
|
}
|
|
|
|
public void dispatchLongPress() {
|
|
this.mHandler.removeMessages(3);
|
|
this.mDeferConfirmSingleTap = false;
|
|
this.mInLongPress = true;
|
|
this.mListener.onLongPress(this.mCurrentDownEvent);
|
|
}
|
|
|
|
@Override // androidx.core.view.GestureDetectorCompat.GestureDetectorCompatImpl
|
|
public boolean isLongpressEnabled() {
|
|
return this.mIsLongpressEnabled;
|
|
}
|
|
|
|
/* JADX WARNING: Removed duplicated region for block: B:100:0x0208 */
|
|
/* JADX WARNING: Removed duplicated region for block: B:103:0x021f */
|
|
@Override // androidx.core.view.GestureDetectorCompat.GestureDetectorCompatImpl
|
|
public boolean onTouchEvent(MotionEvent motionEvent) {
|
|
boolean z2;
|
|
MotionEvent motionEvent2;
|
|
MotionEvent motionEvent3;
|
|
boolean z3;
|
|
GestureDetector.OnDoubleTapListener onDoubleTapListener;
|
|
int action = motionEvent.getAction();
|
|
if (this.mVelocityTracker == null) {
|
|
this.mVelocityTracker = VelocityTracker.obtain();
|
|
}
|
|
this.mVelocityTracker.addMovement(motionEvent);
|
|
int i = action & 255;
|
|
boolean z4 = i == 6;
|
|
int actionIndex = z4 ? motionEvent.getActionIndex() : -1;
|
|
int pointerCount = motionEvent.getPointerCount();
|
|
float f = 0.0f;
|
|
float f2 = 0.0f;
|
|
for (int i2 = 0; i2 < pointerCount; i2++) {
|
|
if (actionIndex != i2) {
|
|
f += motionEvent.getX(i2);
|
|
f2 += motionEvent.getY(i2);
|
|
}
|
|
}
|
|
float f3 = (float) (z4 ? pointerCount - 1 : pointerCount);
|
|
float f4 = f / f3;
|
|
float f5 = f2 / f3;
|
|
if (i != 0) {
|
|
if (i == 1) {
|
|
this.mStillDown = false;
|
|
MotionEvent obtain = MotionEvent.obtain(motionEvent);
|
|
if (this.mIsDoubleTapping) {
|
|
z3 = this.mDoubleTapListener.onDoubleTapEvent(motionEvent) | false;
|
|
} else {
|
|
if (this.mInLongPress) {
|
|
this.mHandler.removeMessages(3);
|
|
this.mInLongPress = false;
|
|
} else if (this.mAlwaysInTapRegion) {
|
|
boolean onSingleTapUp = this.mListener.onSingleTapUp(motionEvent);
|
|
if (this.mDeferConfirmSingleTap && (onDoubleTapListener = this.mDoubleTapListener) != null) {
|
|
onDoubleTapListener.onSingleTapConfirmed(motionEvent);
|
|
}
|
|
z3 = onSingleTapUp;
|
|
} else {
|
|
VelocityTracker velocityTracker = this.mVelocityTracker;
|
|
int pointerId = motionEvent.getPointerId(0);
|
|
velocityTracker.computeCurrentVelocity(1000, (float) this.mMaximumFlingVelocity);
|
|
float yVelocity = velocityTracker.getYVelocity(pointerId);
|
|
float xVelocity = velocityTracker.getXVelocity(pointerId);
|
|
if (Math.abs(yVelocity) > ((float) this.mMinimumFlingVelocity) || Math.abs(xVelocity) > ((float) this.mMinimumFlingVelocity)) {
|
|
z3 = this.mListener.onFling(this.mCurrentDownEvent, motionEvent, xVelocity, yVelocity);
|
|
}
|
|
}
|
|
z3 = false;
|
|
}
|
|
MotionEvent motionEvent4 = this.mPreviousUpEvent;
|
|
if (motionEvent4 != null) {
|
|
motionEvent4.recycle();
|
|
}
|
|
this.mPreviousUpEvent = obtain;
|
|
VelocityTracker velocityTracker2 = this.mVelocityTracker;
|
|
if (velocityTracker2 != null) {
|
|
velocityTracker2.recycle();
|
|
this.mVelocityTracker = null;
|
|
}
|
|
this.mIsDoubleTapping = false;
|
|
this.mDeferConfirmSingleTap = false;
|
|
this.mHandler.removeMessages(1);
|
|
this.mHandler.removeMessages(2);
|
|
} else if (i != 2) {
|
|
if (i == 3) {
|
|
cancel();
|
|
return false;
|
|
} else if (i == 5) {
|
|
this.mLastFocusX = f4;
|
|
this.mDownFocusX = f4;
|
|
this.mLastFocusY = f5;
|
|
this.mDownFocusY = f5;
|
|
cancelTaps();
|
|
return false;
|
|
} else if (i != 6) {
|
|
return false;
|
|
} else {
|
|
this.mLastFocusX = f4;
|
|
this.mDownFocusX = f4;
|
|
this.mLastFocusY = f5;
|
|
this.mDownFocusY = f5;
|
|
this.mVelocityTracker.computeCurrentVelocity(1000, (float) this.mMaximumFlingVelocity);
|
|
int actionIndex2 = motionEvent.getActionIndex();
|
|
int pointerId2 = motionEvent.getPointerId(actionIndex2);
|
|
float xVelocity2 = this.mVelocityTracker.getXVelocity(pointerId2);
|
|
float yVelocity2 = this.mVelocityTracker.getYVelocity(pointerId2);
|
|
for (int i3 = 0; i3 < pointerCount; i3++) {
|
|
if (i3 != actionIndex2) {
|
|
int pointerId3 = motionEvent.getPointerId(i3);
|
|
if ((this.mVelocityTracker.getYVelocity(pointerId3) * yVelocity2) + (this.mVelocityTracker.getXVelocity(pointerId3) * xVelocity2) < 0.0f) {
|
|
this.mVelocityTracker.clear();
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
} else if (this.mInLongPress) {
|
|
return false;
|
|
} else {
|
|
float f6 = this.mLastFocusX - f4;
|
|
float f7 = this.mLastFocusY - f5;
|
|
if (this.mIsDoubleTapping) {
|
|
return false | this.mDoubleTapListener.onDoubleTapEvent(motionEvent);
|
|
}
|
|
if (this.mAlwaysInTapRegion) {
|
|
int i4 = (int) (f4 - this.mDownFocusX);
|
|
int i5 = (int) (f5 - this.mDownFocusY);
|
|
int i6 = (i5 * i5) + (i4 * i4);
|
|
if (i6 > this.mTouchSlopSquare) {
|
|
z3 = this.mListener.onScroll(this.mCurrentDownEvent, motionEvent, f6, f7);
|
|
this.mLastFocusX = f4;
|
|
this.mLastFocusY = f5;
|
|
this.mAlwaysInTapRegion = false;
|
|
this.mHandler.removeMessages(3);
|
|
this.mHandler.removeMessages(1);
|
|
this.mHandler.removeMessages(2);
|
|
} else {
|
|
z3 = false;
|
|
}
|
|
if (i6 > this.mTouchSlopSquare) {
|
|
this.mAlwaysInBiggerTapRegion = false;
|
|
}
|
|
} else if (Math.abs(f6) < 1.0f && Math.abs(f7) < 1.0f) {
|
|
return false;
|
|
} else {
|
|
boolean onScroll = this.mListener.onScroll(this.mCurrentDownEvent, motionEvent, f6, f7);
|
|
this.mLastFocusX = f4;
|
|
this.mLastFocusY = f5;
|
|
return onScroll;
|
|
}
|
|
}
|
|
return z3;
|
|
}
|
|
if (this.mDoubleTapListener != null) {
|
|
boolean hasMessages = this.mHandler.hasMessages(3);
|
|
if (hasMessages) {
|
|
this.mHandler.removeMessages(3);
|
|
}
|
|
MotionEvent motionEvent5 = this.mCurrentDownEvent;
|
|
if (motionEvent5 == null || (motionEvent3 = this.mPreviousUpEvent) == null || !hasMessages || !isConsideredDoubleTap(motionEvent5, motionEvent3, motionEvent)) {
|
|
this.mHandler.sendEmptyMessageDelayed(3, (long) DOUBLE_TAP_TIMEOUT);
|
|
} else {
|
|
this.mIsDoubleTapping = true;
|
|
z2 = this.mDoubleTapListener.onDoubleTap(this.mCurrentDownEvent) | false | this.mDoubleTapListener.onDoubleTapEvent(motionEvent);
|
|
this.mLastFocusX = f4;
|
|
this.mDownFocusX = f4;
|
|
this.mLastFocusY = f5;
|
|
this.mDownFocusY = f5;
|
|
motionEvent2 = this.mCurrentDownEvent;
|
|
if (motionEvent2 != null) {
|
|
motionEvent2.recycle();
|
|
}
|
|
this.mCurrentDownEvent = MotionEvent.obtain(motionEvent);
|
|
this.mAlwaysInTapRegion = true;
|
|
this.mAlwaysInBiggerTapRegion = true;
|
|
this.mStillDown = true;
|
|
this.mInLongPress = false;
|
|
this.mDeferConfirmSingleTap = false;
|
|
if (this.mIsLongpressEnabled) {
|
|
this.mHandler.removeMessages(2);
|
|
this.mHandler.sendEmptyMessageAtTime(2, this.mCurrentDownEvent.getDownTime() + ((long) TAP_TIMEOUT) + ((long) LONGPRESS_TIMEOUT));
|
|
}
|
|
this.mHandler.sendEmptyMessageAtTime(1, this.mCurrentDownEvent.getDownTime() + ((long) TAP_TIMEOUT));
|
|
return z2 | this.mListener.onDown(motionEvent);
|
|
}
|
|
}
|
|
z2 = false;
|
|
this.mLastFocusX = f4;
|
|
this.mDownFocusX = f4;
|
|
this.mLastFocusY = f5;
|
|
this.mDownFocusY = f5;
|
|
motionEvent2 = this.mCurrentDownEvent;
|
|
if (motionEvent2 != null) {
|
|
}
|
|
this.mCurrentDownEvent = MotionEvent.obtain(motionEvent);
|
|
this.mAlwaysInTapRegion = true;
|
|
this.mAlwaysInBiggerTapRegion = true;
|
|
this.mStillDown = true;
|
|
this.mInLongPress = false;
|
|
this.mDeferConfirmSingleTap = false;
|
|
if (this.mIsLongpressEnabled) {
|
|
}
|
|
this.mHandler.sendEmptyMessageAtTime(1, this.mCurrentDownEvent.getDownTime() + ((long) TAP_TIMEOUT));
|
|
return z2 | this.mListener.onDown(motionEvent);
|
|
}
|
|
|
|
@Override // androidx.core.view.GestureDetectorCompat.GestureDetectorCompatImpl
|
|
public void setIsLongpressEnabled(boolean z2) {
|
|
this.mIsLongpressEnabled = z2;
|
|
}
|
|
|
|
@Override // androidx.core.view.GestureDetectorCompat.GestureDetectorCompatImpl
|
|
public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener) {
|
|
this.mDoubleTapListener = onDoubleTapListener;
|
|
}
|
|
}
|
|
|
|
public static class GestureDetectorCompatImplJellybeanMr2 implements GestureDetectorCompatImpl {
|
|
private final GestureDetector mDetector;
|
|
|
|
public GestureDetectorCompatImplJellybeanMr2(Context context, GestureDetector.OnGestureListener onGestureListener, Handler handler) {
|
|
this.mDetector = new GestureDetector(context, onGestureListener, handler);
|
|
}
|
|
|
|
@Override // androidx.core.view.GestureDetectorCompat.GestureDetectorCompatImpl
|
|
public boolean isLongpressEnabled() {
|
|
return this.mDetector.isLongpressEnabled();
|
|
}
|
|
|
|
@Override // androidx.core.view.GestureDetectorCompat.GestureDetectorCompatImpl
|
|
public boolean onTouchEvent(MotionEvent motionEvent) {
|
|
return this.mDetector.onTouchEvent(motionEvent);
|
|
}
|
|
|
|
@Override // androidx.core.view.GestureDetectorCompat.GestureDetectorCompatImpl
|
|
public void setIsLongpressEnabled(boolean z2) {
|
|
this.mDetector.setIsLongpressEnabled(z2);
|
|
}
|
|
|
|
@Override // androidx.core.view.GestureDetectorCompat.GestureDetectorCompatImpl
|
|
public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener) {
|
|
this.mDetector.setOnDoubleTapListener(onDoubleTapListener);
|
|
}
|
|
}
|
|
|
|
public GestureDetectorCompat(Context context, GestureDetector.OnGestureListener onGestureListener) {
|
|
this(context, onGestureListener, null);
|
|
}
|
|
|
|
public GestureDetectorCompat(Context context, GestureDetector.OnGestureListener onGestureListener, Handler handler) {
|
|
this.mImpl = new GestureDetectorCompatImplJellybeanMr2(context, onGestureListener, handler);
|
|
}
|
|
|
|
public boolean isLongpressEnabled() {
|
|
return this.mImpl.isLongpressEnabled();
|
|
}
|
|
|
|
public boolean onTouchEvent(MotionEvent motionEvent) {
|
|
return this.mImpl.onTouchEvent(motionEvent);
|
|
}
|
|
|
|
public void setIsLongpressEnabled(boolean z2) {
|
|
this.mImpl.setIsLongpressEnabled(z2);
|
|
}
|
|
|
|
public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener) {
|
|
this.mImpl.setOnDoubleTapListener(onDoubleTapListener);
|
|
}
|
|
}
|