Merge "Make AccessibilityGestureDetector handle gesture detection start and end."
This commit is contained in:
@@ -27,6 +27,8 @@ import android.gesture.Prediction;
|
||||
import android.util.Slog;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
@@ -46,7 +48,9 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen
|
||||
public interface Listener {
|
||||
public void onDoubleTapAndHold(MotionEvent event, int policyFlags);
|
||||
public boolean onDoubleTap(MotionEvent event, int policyFlags);
|
||||
public boolean onGesture(int gestureId);
|
||||
public boolean onGestureCompleted(int gestureId);
|
||||
public void onGestureStarted();
|
||||
public void onGestureCancelled(MotionEvent event, int policyFlags);
|
||||
}
|
||||
|
||||
private final Listener mListener;
|
||||
@@ -64,6 +68,10 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen
|
||||
// Indicates that motion events are being collected to match a gesture.
|
||||
private boolean mRecognizingGesture;
|
||||
|
||||
// Indicates that we've collected enough data to be sure it could be a
|
||||
// gesture.
|
||||
private boolean mGestureConfirmed;
|
||||
|
||||
// Indicates that motion events from the second pointer are being checked
|
||||
// for a double tap.
|
||||
private boolean mSecondFingerDoubleTap;
|
||||
@@ -81,18 +89,41 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen
|
||||
// The Y of the previous event.
|
||||
private float mPreviousY;
|
||||
|
||||
// The X of the down event.
|
||||
private float mBaseX;
|
||||
|
||||
// The Y of the down event.
|
||||
private float mBaseY;
|
||||
|
||||
// Slop between the first and second tap to be a double tap.
|
||||
private final int mDoubleTapSlop;
|
||||
|
||||
// The scaled velocity above which we detect gestures.
|
||||
private final int mScaledGestureDetectionVelocity;
|
||||
|
||||
// Buffer for storing points for gesture detection.
|
||||
private final ArrayList<GesturePoint> mStrokeBuffer = new ArrayList<GesturePoint>(100);
|
||||
|
||||
// Helper to track gesture velocity.
|
||||
private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
|
||||
|
||||
// The minimal delta between moves to add a gesture point.
|
||||
private static final int TOUCH_TOLERANCE = 3;
|
||||
|
||||
// The minimal score for accepting a predicted gesture.
|
||||
private static final float MIN_PREDICTION_SCORE = 2.0f;
|
||||
|
||||
// The velocity above which we detect gestures. Expressed in DIPs/Second.
|
||||
private static final int GESTURE_DETECTION_VELOCITY_DIP = 1000;
|
||||
|
||||
// Constant used to calculate velocity in seconds.
|
||||
private static final int VELOCITY_UNITS_SECONDS = 1000;
|
||||
|
||||
AccessibilityGestureDetector(Context context, Listener listener) {
|
||||
mListener = listener;
|
||||
|
||||
mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
|
||||
|
||||
mGestureDetector = new GestureDetector(context, this);
|
||||
mGestureDetector.setOnDoubleTapListener(this);
|
||||
|
||||
@@ -100,9 +131,14 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen
|
||||
mGestureLibrary.setOrientationStyle(8 /* GestureStore.ORIENTATION_SENSITIVE_8 */);
|
||||
mGestureLibrary.setSequenceType(GestureStore.SEQUENCE_SENSITIVE);
|
||||
mGestureLibrary.load();
|
||||
|
||||
final float density = context.getResources().getDisplayMetrics().density;
|
||||
mScaledGestureDetectionVelocity = (int) (GESTURE_DETECTION_VELOCITY_DIP * density);
|
||||
}
|
||||
|
||||
public boolean onMotionEvent(MotionEvent event, int policyFlags) {
|
||||
mVelocityTracker.addMovement(event);
|
||||
|
||||
final float x = event.getX();
|
||||
final float y = event.getY();
|
||||
|
||||
@@ -112,14 +148,48 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen
|
||||
mDoubleTapDetected = false;
|
||||
mSecondFingerDoubleTap = false;
|
||||
mRecognizingGesture = true;
|
||||
mGestureConfirmed = false;
|
||||
mBaseX = x;
|
||||
mBaseY = y;
|
||||
mPreviousX = x;
|
||||
mPreviousY = y;
|
||||
mStrokeBuffer.clear();
|
||||
mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
|
||||
mVelocityTracker.clear();
|
||||
mVelocityTracker.addMovement(event);
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (mRecognizingGesture) {
|
||||
if (!mGestureConfirmed) {
|
||||
mVelocityTracker.addMovement(event);
|
||||
// It is *important* to use the distance traveled by the pointers
|
||||
// on the screen which may or may not be magnified.
|
||||
final float deltaX = mBaseX - event.getX(0);
|
||||
final float deltaY = mBaseY - event.getY(0);
|
||||
final double moveDelta = Math.hypot(deltaX, deltaY);
|
||||
// The user has moved enough for us to decide.
|
||||
if (moveDelta > mDoubleTapSlop) {
|
||||
// Check whether the user is performing a gesture. We
|
||||
// detect gestures if the pointer is moving above a
|
||||
// given velocity.
|
||||
mVelocityTracker.computeCurrentVelocity(VELOCITY_UNITS_SECONDS);
|
||||
final float maxAbsVelocity = Math.max(
|
||||
Math.abs(mVelocityTracker.getXVelocity(0)),
|
||||
Math.abs(mVelocityTracker.getYVelocity(0)));
|
||||
if (maxAbsVelocity > mScaledGestureDetectionVelocity) {
|
||||
// We have to perform gesture detection, so
|
||||
// notify the listener.
|
||||
mGestureConfirmed = true;
|
||||
mListener.onGestureStarted();
|
||||
} else {
|
||||
// This won't match any gesture, so notify the
|
||||
// listener.
|
||||
cancelGesture();
|
||||
mListener.onGestureCancelled(event, policyFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
final float dX = Math.abs(x - mPreviousX);
|
||||
final float dY = Math.abs(y - mPreviousY);
|
||||
if (dX >= TOUCH_TOLERANCE || dY >= TOUCH_TOLERANCE) {
|
||||
@@ -134,12 +204,13 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen
|
||||
if (maybeFinishDoubleTap(event, policyFlags)) {
|
||||
return true;
|
||||
}
|
||||
if (mRecognizingGesture) {
|
||||
if (mGestureConfirmed) {
|
||||
mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
|
||||
|
||||
if (recognizeGesture()) {
|
||||
return true;
|
||||
if (!recognizeGesture()) {
|
||||
mListener.onGestureCancelled(event, policyFlags);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -167,6 +238,10 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
clear();
|
||||
break;
|
||||
}
|
||||
|
||||
// If we're detecting taps on the second finger, map events from the
|
||||
@@ -194,18 +269,13 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen
|
||||
mDoubleTapDetected = false;
|
||||
mSecondFingerDoubleTap = false;
|
||||
cancelGesture();
|
||||
mStrokeBuffer.clear();
|
||||
mVelocityTracker.clear();
|
||||
}
|
||||
|
||||
public boolean firstTapDetected() {
|
||||
return mFirstTapDetected;
|
||||
}
|
||||
|
||||
public void cancelGesture() {
|
||||
mRecognizingGesture = false;
|
||||
mStrokeBuffer.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLongPress(MotionEvent e) {
|
||||
maybeSendLongPress(e, mPolicyFlags);
|
||||
@@ -251,6 +321,12 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen
|
||||
return mListener.onDoubleTap(event, policyFlags);
|
||||
}
|
||||
|
||||
private void cancelGesture() {
|
||||
mRecognizingGesture = false;
|
||||
mGestureConfirmed = false;
|
||||
mStrokeBuffer.clear();
|
||||
}
|
||||
|
||||
private boolean recognizeGesture() {
|
||||
Gesture gesture = new Gesture();
|
||||
gesture.addStroke(new GestureStroke(mStrokeBuffer));
|
||||
@@ -265,7 +341,7 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen
|
||||
}
|
||||
try {
|
||||
final int gestureId = Integer.parseInt(bestPrediction.name);
|
||||
if (mListener.onGesture(gestureId)) {
|
||||
if (mListener.onGestureCompleted(gestureId)) {
|
||||
return true;
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
|
||||
@@ -25,7 +25,6 @@ import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.MotionEvent.PointerCoords;
|
||||
import android.view.MotionEvent.PointerProperties;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.WindowManagerPolicy;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
@@ -87,9 +86,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
// Invalid pointer ID.
|
||||
private static final int INVALID_POINTER_ID = -1;
|
||||
|
||||
// The velocity above which we detect gestures.
|
||||
private static final int GESTURE_DETECTION_VELOCITY_DIP = 1000;
|
||||
|
||||
// The minimal distance before we take the middle of the distance between
|
||||
// the two dragging pointers as opposed to use the location of the primary one.
|
||||
private static final int MIN_POINTER_DISTANCE_TO_USE_MIDDLE_LOCATION_DIP = 200;
|
||||
@@ -134,15 +130,9 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
// the two dragging pointers as opposed to use the location of the primary one.
|
||||
private final int mScaledMinPointerDistanceToUseMiddleLocation;
|
||||
|
||||
// The scaled velocity above which we detect gestures.
|
||||
private final int mScaledGestureDetectionVelocity;
|
||||
|
||||
// The handler to which to delegate events.
|
||||
private EventStreamTransformation mNext;
|
||||
|
||||
// Helper to track gesture velocity.
|
||||
private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
|
||||
|
||||
// Helper class to track received pointers.
|
||||
private final ReceivedPointerTracker mReceivedPointerTracker;
|
||||
|
||||
@@ -200,7 +190,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
final float density = context.getResources().getDisplayMetrics().density;
|
||||
mScaledMinPointerDistanceToUseMiddleLocation =
|
||||
(int) (MIN_POINTER_DISTANCE_TO_USE_MIDDLE_LOCATION_DIP * density);
|
||||
mScaledGestureDetectionVelocity = (int) (GESTURE_DETECTION_VELOCITY_DIP * density);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -289,11 +278,19 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
|
||||
mReceivedPointerTracker.onMotionEvent(rawEvent);
|
||||
|
||||
if (mGestureDetector.onMotionEvent(event, policyFlags)) {
|
||||
// The motion detector is interested in the movements in physical space,
|
||||
// so it uses the rawEvent to ignore magnification and other
|
||||
// transformations.
|
||||
if (mGestureDetector.onMotionEvent(rawEvent, policyFlags)) {
|
||||
// Event was handled by the gesture detector.
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
|
||||
clear(event, policyFlags);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(mCurrentState) {
|
||||
case STATE_TOUCH_EXPLORING: {
|
||||
handleMotionEventStateTouchExploring(event, rawEvent, policyFlags);
|
||||
@@ -305,7 +302,7 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
handleMotionEventStateDelegating(event, policyFlags);
|
||||
} break;
|
||||
case STATE_GESTURE_DETECTING: {
|
||||
handleMotionEventGestureDetecting(rawEvent, policyFlags);
|
||||
// Already handled.
|
||||
} break;
|
||||
default:
|
||||
throw new IllegalStateException("Illegal state: " + mCurrentState);
|
||||
@@ -440,26 +437,50 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onGesture(int gestureId) {
|
||||
public boolean onGestureCompleted(int gestureId) {
|
||||
if (mCurrentState != STATE_GESTURE_DETECTING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mAms.onTouchInteractionEnd();
|
||||
|
||||
// Announce the end of the gesture recognition.
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
|
||||
// Announce the end of a the touch interaction.
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
|
||||
endGestureDetection();
|
||||
|
||||
mAms.onGesture(gestureId);
|
||||
|
||||
mExitGestureDetectionModeDelayed.cancel();
|
||||
mCurrentState = STATE_TOUCH_EXPLORING;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGestureStarted() {
|
||||
// We have to perform gesture detection, so
|
||||
// clear the current state and try to detect.
|
||||
mCurrentState = STATE_GESTURE_DETECTING;
|
||||
mSendHoverEnterAndMoveDelayed.cancel();
|
||||
mSendHoverExitDelayed.cancel();
|
||||
mExitGestureDetectionModeDelayed.post();
|
||||
// Send accessibility event to announce the start
|
||||
// of gesture recognition.
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_START);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGestureCancelled(MotionEvent event, int policyFlags) {
|
||||
if (mCurrentState == STATE_GESTURE_DETECTING) {
|
||||
endGestureDetection();
|
||||
} else if (mCurrentState == STATE_TOUCH_EXPLORING) {
|
||||
final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
|
||||
final int pointerIdBits = (1 << pointerId);
|
||||
|
||||
// Cache the event until we discern exploration from gesturing.
|
||||
mSendHoverEnterAndMoveDelayed.addEvent(event);
|
||||
|
||||
// We have just decided that the user is touch,
|
||||
// exploring so start sending events.
|
||||
mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
|
||||
mSendHoverExitDelayed.cancel();
|
||||
sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a motion event in touch exploring state.
|
||||
*
|
||||
@@ -471,8 +492,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
int policyFlags) {
|
||||
ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
|
||||
|
||||
mVelocityTracker.addMovement(rawEvent);
|
||||
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
mAms.onTouchInteractionStart();
|
||||
@@ -525,46 +544,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
if (mSendHoverEnterAndMoveDelayed.isPending()) {
|
||||
// Cache the event until we discern exploration from gesturing.
|
||||
mSendHoverEnterAndMoveDelayed.addEvent(event);
|
||||
|
||||
// It is *important* to use the distance traveled by the pointers
|
||||
// on the screen which may or may not be magnified.
|
||||
final float deltaX = receivedTracker.getReceivedPointerDownX(pointerId)
|
||||
- rawEvent.getX(pointerIndex);
|
||||
final float deltaY = receivedTracker.getReceivedPointerDownY(pointerId)
|
||||
- rawEvent.getY(pointerIndex);
|
||||
final double moveDelta = Math.hypot(deltaX, deltaY);
|
||||
// The user has moved enough for us to decide.
|
||||
if (moveDelta > mDoubleTapSlop) {
|
||||
// Check whether the user is performing a gesture. We
|
||||
// detect gestures if the pointer is moving above a
|
||||
// given velocity.
|
||||
mVelocityTracker.computeCurrentVelocity(1000);
|
||||
final float maxAbsVelocity = Math.max(
|
||||
Math.abs(mVelocityTracker.getXVelocity(pointerId)),
|
||||
Math.abs(mVelocityTracker.getYVelocity(pointerId)));
|
||||
if (maxAbsVelocity > mScaledGestureDetectionVelocity) {
|
||||
// We have to perform gesture detection, so
|
||||
// clear the current state and try to detect.
|
||||
mCurrentState = STATE_GESTURE_DETECTING;
|
||||
mVelocityTracker.clear();
|
||||
mSendHoverEnterAndMoveDelayed.cancel();
|
||||
mSendHoverExitDelayed.cancel();
|
||||
mExitGestureDetectionModeDelayed.post();
|
||||
// Send accessibility event to announce the start
|
||||
// of gesture recognition.
|
||||
sendAccessibilityEvent(
|
||||
AccessibilityEvent.TYPE_GESTURE_DETECTION_START);
|
||||
} else {
|
||||
// We have just decided that the user is touch,
|
||||
// exploring so start sending events.
|
||||
mGestureDetector.cancelGesture();
|
||||
mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
|
||||
mSendHoverExitDelayed.cancel();
|
||||
sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE,
|
||||
pointerIdBits, policyFlags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (mTouchExplorationInProgress) {
|
||||
sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags);
|
||||
@@ -602,11 +581,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
}
|
||||
}
|
||||
|
||||
// We know that a new state transition is to happen and the
|
||||
// new state will not be gesture recognition, so cancel
|
||||
// the gesture.
|
||||
mGestureDetector.cancelGesture();
|
||||
|
||||
if (isDraggingGesture(event)) {
|
||||
// Two pointers moving in the same direction within
|
||||
// a given distance perform a drag.
|
||||
@@ -620,7 +594,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
mCurrentState = STATE_DELEGATING;
|
||||
sendDownForAllNotInjectedPointers(event, policyFlags);
|
||||
}
|
||||
mVelocityTracker.clear();
|
||||
} break;
|
||||
default: {
|
||||
// More than one pointer so the user is not touch exploring
|
||||
@@ -639,7 +612,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
// More than two pointers are delegated to the view hierarchy.
|
||||
mCurrentState = STATE_DELEGATING;
|
||||
sendDownForAllNotInjectedPointers(event, policyFlags);
|
||||
mVelocityTracker.clear();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -648,8 +620,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
final int pointerId = event.getPointerId(event.getActionIndex());
|
||||
final int pointerIdBits = (1 << pointerId);
|
||||
|
||||
mVelocityTracker.clear();
|
||||
|
||||
if (mSendHoverEnterAndMoveDelayed.isPending()) {
|
||||
// If we have not delivered the enter schedule an exit.
|
||||
mSendHoverExitDelayed.post(event, pointerIdBits, policyFlags);
|
||||
@@ -663,9 +633,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
}
|
||||
|
||||
} break;
|
||||
case MotionEvent.ACTION_CANCEL: {
|
||||
clear(event, policyFlags);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -756,9 +723,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
}
|
||||
mCurrentState = STATE_TOUCH_EXPLORING;
|
||||
} break;
|
||||
case MotionEvent.ACTION_CANCEL: {
|
||||
clear(event, policyFlags);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -795,9 +759,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
|
||||
mCurrentState = STATE_TOUCH_EXPLORING;
|
||||
} break;
|
||||
case MotionEvent.ACTION_CANCEL: {
|
||||
clear(event, policyFlags);
|
||||
} break;
|
||||
default: {
|
||||
// Deliver the event.
|
||||
sendMotionEvent(event, event.getAction(), ALL_POINTER_ID_BITS, policyFlags);
|
||||
@@ -805,22 +766,16 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMotionEventGestureDetecting(MotionEvent event, int policyFlags) {
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_UP: {
|
||||
mAms.onTouchInteractionEnd();
|
||||
// Announce the end of the gesture recognition.
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
|
||||
// Announce the end of a the touch interaction.
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
|
||||
private void endGestureDetection() {
|
||||
mAms.onTouchInteractionEnd();
|
||||
|
||||
mExitGestureDetectionModeDelayed.cancel();
|
||||
mCurrentState = STATE_TOUCH_EXPLORING;
|
||||
} break;
|
||||
case MotionEvent.ACTION_CANCEL: {
|
||||
clear(event, policyFlags);
|
||||
} break;
|
||||
}
|
||||
// Announce the end of the gesture recognition.
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
|
||||
// Announce the end of a the touch interaction.
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
|
||||
|
||||
mExitGestureDetectionModeDelayed.cancel();
|
||||
mCurrentState = STATE_TOUCH_EXPLORING;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user