@Override public boolean onTouchEvent(MotionEvent event) { // Avoid short-circuit logic evaluation - ensure all gesture detectors see all events so // that they generate correct notifications. boolean handled = mScroller.onTouchEvent(event); handled |= mZoomer.onTouchEvent(event); handled |= mTapDetector.onTouchEvent(event); mSwipePinchDetector.onTouchEvent(event); switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: mViewer.setAnimationEnabled(false); mSuppressCursorMovement = false; mSuppressFling = false; mSwipeCompleted = false; break; case MotionEvent.ACTION_POINTER_DOWN: mTotalMotionY = 0; break; case MotionEvent.ACTION_UP: releaseAnyHeldButton(); break; default: break; } return handled; }
/** Processes a (multi-finger) swipe gesture. */ private boolean onSwipe() { if (mTotalMotionY > mSwipeThreshold) { // Swipe down occurred. mViewer.showActionBar(); } else if (mTotalMotionY < -mSwipeThreshold) { // Swipe up occurred. mViewer.showKeyboard(); } else { return false; } mSuppressCursorMovement = true; mSuppressFling = true; mSwipeCompleted = true; return true; }
/** Moves the mouse-cursor, injects a mouse-move event and repositions the image. */ private void moveCursor(float newX, float newY) { synchronized (mRenderData) { // Constrain cursor to the image area. if (newX < 0) newX = 0; if (newY < 0) newY = 0; if (newX > mRenderData.imageWidth) newX = mRenderData.imageWidth; if (newY > mRenderData.imageHeight) newY = mRenderData.imageHeight; mCursorPosition.set(newX, newY); repositionImage(); } mViewer.injectMouseEvent((int) newX, (int) newY, BUTTON_UNDEFINED, false); }
/** * Repositions the image by translating it (without affecting the zoom level) to place the cursor * close to the center of the screen. */ private void repositionImage() { synchronized (mRenderData) { // Get the current cursor position in screen coordinates. float[] cursorScreen = {mCursorPosition.x, mCursorPosition.y}; mRenderData.transform.mapPoints(cursorScreen); // Translate so the cursor is displayed in the middle of the screen. mRenderData.transform.postTranslate( (float) mRenderData.screenWidth / 2 - cursorScreen[0], (float) mRenderData.screenHeight / 2 - cursorScreen[1]); // Now the cursor is displayed in the middle of the screen, see if the image can be // panned so that more of it is visible. The primary goal is to show as much of the // image as possible. The secondary goal is to keep the cursor in the middle. // Get the coordinates of the desktop rectangle (top-left/bottom-right corners) in // screen coordinates. Order is: left, top, right, bottom. float[] rectScreen = {0, 0, mRenderData.imageWidth, mRenderData.imageHeight}; mRenderData.transform.mapPoints(rectScreen); float leftDelta = rectScreen[0]; float rightDelta = rectScreen[2] - mRenderData.screenWidth; float topDelta = rectScreen[1]; float bottomDelta = rectScreen[3] - mRenderData.screenHeight; float xAdjust = 0; float yAdjust = 0; if (rectScreen[2] - rectScreen[0] < mRenderData.screenWidth) { // Image is narrower than the screen, so center it. xAdjust = -(rightDelta + leftDelta) / 2; } else if (leftDelta > 0 && rightDelta > 0) { // Panning the image left will show more of it. xAdjust = -Math.min(leftDelta, rightDelta); } else if (leftDelta < 0 && rightDelta < 0) { // Pan the image right. xAdjust = Math.min(-leftDelta, -rightDelta); } // Apply similar logic for yAdjust. if (rectScreen[3] - rectScreen[1] < mRenderData.screenHeight) { yAdjust = -(bottomDelta + topDelta) / 2; } else if (topDelta > 0 && bottomDelta > 0) { yAdjust = -Math.min(topDelta, bottomDelta); } else if (topDelta < 0 && bottomDelta < 0) { yAdjust = Math.min(-topDelta, -bottomDelta); } mRenderData.transform.postTranslate(xAdjust, yAdjust); } mViewer.transformationChanged(); }
@Override public void processAnimation() { int previousX = mFlingScroller.getCurrX(); int previousY = mFlingScroller.getCurrY(); if (!mFlingScroller.computeScrollOffset()) { mViewer.setAnimationEnabled(false); return; } int deltaX = mFlingScroller.getCurrX() - previousX; int deltaY = mFlingScroller.getCurrY() - previousY; float[] delta = {deltaX, deltaY}; synchronized (mRenderData) { Matrix canvasToImage = new Matrix(); mRenderData.transform.invert(canvasToImage); canvasToImage.mapVectors(delta); } moveCursor(mCursorPosition.x + delta[0], mCursorPosition.y + delta[1]); }
/** Injects a button event using the current cursor location. */ private void injectButtonEvent(int button, boolean pressed) { mViewer.injectMouseEvent((int) mCursorPosition.x, (int) mCursorPosition.y, button, pressed); }