/* * Copyright (c) 2013 Menny Even-Danan * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.anysoftkeyboard.keyboards.views; import android.view.MotionEvent; import com.anysoftkeyboard.devicespecific.AskOnGestureListener; import com.anysoftkeyboard.utils.Log; final class AskGestureEventsListener implements AskOnGestureListener { private static final String TAG = "AskGestureEventsListener"; private final AnyKeyboardBaseView mKeyboardView; public AskGestureEventsListener(AnyKeyboardBaseView keyboardView) { mKeyboardView = keyboardView; } public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (mKeyboardView.isAtTwoFingersState()) { //in two fingers state we might still want to report a scroll, if BOTH pointers are moving in the same direction if (!pointersMovingInTheSameDirection(e1, e2)) { return false; } } final float scrollXDistance = Math.abs(e2.getX() - e1.getX()); final float scrollYDistance = Math.abs(e2.getY() - e1.getY()); final float totalScrollTime = ((float) (e2.getEventTime() - e1.getEventTime())); //velocity is per second, not per millisecond. final float velocityX = 1000 * Math.abs(scrollXDistance / totalScrollTime); final float velocityY = 1000 * Math.abs(scrollYDistance / totalScrollTime); Log.d(TAG, "onScroll scrollX %f, scrollY %f, velocityX %f, velocityY %f", scrollXDistance, scrollYDistance, velocityX, velocityY); if (velocityX > velocityY) { Log.v(TAG, "Scrolling on X axis"); if (velocityX > mKeyboardView.mSwipeVelocityThreshold) { Log.v(TAG, "Scroll broke the velocity barrier"); final int swipeXDistance = mKeyboardView.isFirstDownEventInsideSpaceBar() ? mKeyboardView.mSwipeSpaceXDistanceThreshold : mKeyboardView.mSwipeXDistanceThreshold; if (scrollXDistance > swipeXDistance) { Log.v(TAG, "Scroll broke the distance barrier"); mKeyboardView.disableTouchesTillFingersAreUp(); if (e2.getX() > e1.getX()) { //to right mKeyboardView.mKeyboardActionListener.onSwipeRight( mKeyboardView.isFirstDownEventInsideSpaceBar(), mKeyboardView.isAtTwoFingersState()); } else { mKeyboardView.mKeyboardActionListener.onSwipeLeft( mKeyboardView.isFirstDownEventInsideSpaceBar(), mKeyboardView.isAtTwoFingersState()); } return true; } } } return false; } private static final int DIRECTION_NONE = -1; private static final int DIRECTION_UP = 0; private static final int DIRECTION_DOWN = 1; private static final int DIRECTION_LEFT = 2; private static final int DIRECTION_RIGHT = 3; private static int getPointerDirection(MotionEvent e1, MotionEvent e2, final int pointerIndex) { final int pointerId = e1.getPointerId(pointerIndex); final int secondPointerIndex = e2.findPointerIndex(pointerId); if (secondPointerIndex == -1) return DIRECTION_NONE; final float xDistance = e2.getX(secondPointerIndex) - e1.getX(pointerIndex); final float yDistance = e2.getY(secondPointerIndex) - e1.getY(pointerIndex); if (xDistance == yDistance) return DIRECTION_NONE; if (Math.abs(xDistance) > Math.abs(yDistance)) { //major movement in the X axis if (xDistance > 0) return DIRECTION_RIGHT; else return DIRECTION_LEFT; } else { if (yDistance > 0) return DIRECTION_DOWN; else return DIRECTION_UP; } } private static boolean pointersMovingInTheSameDirection(MotionEvent e1, MotionEvent e2) { //TODO: PROBLEM, the first event should be the first event with TWO fingers. final int direction = getPointerDirection(e1, e2, 0); for(int pointerIndex = 1; pointerIndex<e2.getPointerCount(); pointerIndex++) { final int otherPointerDirection = getPointerDirection(e1, e2, pointerIndex); if (otherPointerDirection != direction) return false; } //if we got here, it means that all pointers are moving in the same direction return true; } public boolean onFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { if (mKeyboardView.isAtTwoFingersState()) { Log.v(TAG, "onFling ignored due to isAtTwoFingersState"); return false; } final boolean isHorizontalFling = Math.abs(velocityX) > Math.abs(velocityY); Log.d(TAG, "onFling vx %f, vy %f, isHorizontalFling: %s", velocityX, velocityY, Boolean.toString(isHorizontalFling)); float deltaX = me2.getX() - me1.getX(); float deltaY = me2.getY() - me1.getY(); final int swipeXDistance = mKeyboardView.isFirstDownEventInsideSpaceBar() ? mKeyboardView.mSwipeSpaceXDistanceThreshold : mKeyboardView.mSwipeXDistanceThreshold; if (velocityX > mKeyboardView.mSwipeVelocityThreshold && isHorizontalFling && deltaX > swipeXDistance) { mKeyboardView.disableTouchesTillFingersAreUp(); mKeyboardView.mKeyboardActionListener.onSwipeRight(mKeyboardView.isFirstDownEventInsideSpaceBar(), mKeyboardView.isAtTwoFingersState()); return true; } else if (velocityX < -mKeyboardView.mSwipeVelocityThreshold && isHorizontalFling && deltaX < -swipeXDistance) { mKeyboardView.disableTouchesTillFingersAreUp(); mKeyboardView.mKeyboardActionListener.onSwipeLeft(mKeyboardView.isFirstDownEventInsideSpaceBar(), mKeyboardView.isAtTwoFingersState()); return true; } else if (velocityY < -mKeyboardView.mSwipeVelocityThreshold && !isHorizontalFling && deltaY < -mKeyboardView.mSwipeYDistanceThreshold) { mKeyboardView.disableTouchesTillFingersAreUp(); mKeyboardView.mKeyboardActionListener.onSwipeUp(mKeyboardView.isFirstDownEventInsideSpaceBar()); return true; } else if (velocityY > mKeyboardView.mSwipeVelocityThreshold && !isHorizontalFling && deltaY > mKeyboardView.mSwipeYDistanceThreshold) { mKeyboardView.disableTouchesTillFingersAreUp(); mKeyboardView.mKeyboardActionListener.onSwipeDown(mKeyboardView.isFirstDownEventInsideSpaceBar()); return true; } return false; } public boolean onPinch(float factor) { if (factor < 0.65) { mKeyboardView.disableTouchesTillFingersAreUp(); mKeyboardView.mKeyboardActionListener.onPinch(); return true; } return false; } public boolean onSeparate(float factor) { if (factor > 1.35) { mKeyboardView.disableTouchesTillFingersAreUp(); mKeyboardView.mKeyboardActionListener.onSeparate(); return true; } return false; } public boolean onDown(MotionEvent e) { return false; } public void onLongPress(MotionEvent e) { } public void onShowPress(MotionEvent e) { } public boolean onSingleTapUp(MotionEvent e) { return false; } }