/** This function must be called on the UI thread. */ public void preventedTouchFinished() { checkMainThread(); if (mState == PanZoomState.WAITING_LISTENERS) { // if we enter here, we just finished a block of events whose default actions // were prevented by touch listeners. Now there are no touch points left, so // we need to reset our state and re-bounce because we might be in overscroll bounce(); } }
private boolean onTouchCancel(MotionEvent event) { cancelTouch(); if (mState == PanZoomState.WAITING_LISTENERS) { // we might get a cancel event from the TouchEventHandler while in the // WAITING_LISTENERS state if the touch listeners prevent-default the // block of events. at this point being in WAITING_LISTENERS is equivalent // to being in NOTHING with the exception of possibly being in overscroll. // so here we don't want to do anything right now; the overscroll will be // corrected in preventedTouchFinished(). return false; } // ensure we snap back if we're overscrolled bounce(); return false; }
/** * Zoom to a specified rect IN CSS PIXELS. * * <p>While we usually use device pixels, @zoomToRect must be specified in CSS pixels. */ private boolean animatedZoomTo(RectF zoomToRect) { setState(PanZoomState.ANIMATED_ZOOM); final float startZoom = getMetrics().zoomFactor; RectF viewport = getMetrics().getViewport(); // 1. adjust the aspect ratio of zoomToRect to match that of the current viewport, // enlarging as necessary (if it gets too big, it will get shrunk in the next step). // while enlarging make sure we enlarge equally on both sides to keep the target rect // centered. float targetRatio = viewport.width() / viewport.height(); float rectRatio = zoomToRect.width() / zoomToRect.height(); if (FloatUtils.fuzzyEquals(targetRatio, rectRatio)) { // all good, do nothing } else if (targetRatio < rectRatio) { // need to increase zoomToRect height float newHeight = zoomToRect.width() / targetRatio; zoomToRect.top -= (newHeight - zoomToRect.height()) / 2; zoomToRect.bottom = zoomToRect.top + newHeight; } else { // targetRatio > rectRatio) { // need to increase zoomToRect width float newWidth = targetRatio * zoomToRect.height(); zoomToRect.left -= (newWidth - zoomToRect.width()) / 2; zoomToRect.right = zoomToRect.left + newWidth; } float finalZoom = viewport.width() / zoomToRect.width(); ImmutableViewportMetrics finalMetrics = getMetrics(); finalMetrics = finalMetrics.setViewportOrigin( zoomToRect.left * finalMetrics.zoomFactor, zoomToRect.top * finalMetrics.zoomFactor); finalMetrics = finalMetrics.scaleTo(finalZoom, new PointF(0.0f, 0.0f)); // 2. now run getValidViewportMetrics on it, so that the target viewport is // clamped down to prevent overscroll, over-zoom, and other bad conditions. finalMetrics = getValidViewportMetrics(finalMetrics); bounce(finalMetrics); return true; }
private boolean onTouchEnd(MotionEvent event) { switch (mState) { case FLING: case BOUNCE: case WAITING_LISTENERS: // should never happen Log.e(LOGTAG, "Received impossible touch end while in " + mState); // fall through case ANIMATED_ZOOM: case NOTHING: // may happen if user double-taps and drags without lifting after the // second tap. ignore if this happens. return false; case TOUCHING: // the switch into TOUCHING might have happened while the page was // snapping back after overscroll. we need to finish the snap if that // was the case bounce(); return false; case PANNING: case PANNING_LOCKED: case PANNING_HOLD: case PANNING_HOLD_LOCKED: setState(PanZoomState.FLING); fling(); return true; case PINCHING: setState(PanZoomState.NOTHING); return true; } Log.e(LOGTAG, "Unhandled case " + mState + " in onTouchEnd"); return false; }
/* Performs a bounce-back animation to the nearest valid viewport metrics. */ private void bounce() { setState(PanZoomState.BOUNCE); bounce(getValidViewportMetrics()); }
/** This function must be called from the UI thread. */ public void abortPanning() { checkMainThread(); bounce(); }