예제 #1
0
  private ImmutableViewportMetrics getValidViewportMetrics(
      ImmutableViewportMetrics viewportMetrics) {
    /* First, we adjust the zoom factor so that we can make no overscrolled area visible. */
    float zoomFactor = viewportMetrics.zoomFactor;
    RectF pageRect = viewportMetrics.getPageRect();
    RectF viewport = viewportMetrics.getViewport();

    float focusX = viewport.width() / 2.0f;
    float focusY = viewport.height() / 2.0f;

    float minZoomFactor = 0.0f;
    float maxZoomFactor = MAX_ZOOM;

    ZoomConstraints constraints = mTarget.getZoomConstraints();

    if (constraints.getMinZoom() > 0) minZoomFactor = constraints.getMinZoom();
    if (constraints.getMaxZoom() > 0) maxZoomFactor = constraints.getMaxZoom();

    if (!constraints.getAllowZoom()) {
      // If allowZoom is false, clamp to the default zoom level.
      maxZoomFactor = minZoomFactor = constraints.getDefaultZoom();
    }

    // Ensure minZoomFactor keeps the page at least as big as the viewport.
    if (pageRect.width() > 0) {
      float scaleFactor = viewport.width() / pageRect.width();
      minZoomFactor = Math.max(minZoomFactor, zoomFactor * scaleFactor);
      if (viewport.width() > pageRect.width()) focusX = 0.0f;
    }
    if (pageRect.height() > 0) {
      float scaleFactor = viewport.height() / pageRect.height();
      minZoomFactor = Math.max(minZoomFactor, zoomFactor * scaleFactor);
      if (viewport.height() > pageRect.height()) focusY = 0.0f;
    }

    maxZoomFactor = Math.max(maxZoomFactor, minZoomFactor);

    if (zoomFactor < minZoomFactor) {
      // if one (or both) of the page dimensions is smaller than the viewport,
      // zoom using the top/left as the focus on that axis. this prevents the
      // scenario where, if both dimensions are smaller than the viewport, but
      // by different scale factors, we end up scrolled to the end on one axis
      // after applying the scale
      PointF center = new PointF(focusX, focusY);
      viewportMetrics = viewportMetrics.scaleTo(minZoomFactor, center);
    } else if (zoomFactor > maxZoomFactor) {
      PointF center = new PointF(viewport.width() / 2.0f, viewport.height() / 2.0f);
      viewportMetrics = viewportMetrics.scaleTo(maxZoomFactor, center);
    }

    /* Now we pan to the right origin. */
    viewportMetrics = viewportMetrics.clamp();

    return viewportMetrics;
  }
예제 #2
0
  /**
   * 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;
  }
예제 #3
0
 /**
  * Scales the viewport, keeping the given focus point in the same place before and after the scale
  * operation. You must hold the monitor while calling this.
  */
 private void scaleWithFocus(float zoomFactor, PointF focus) {
   ImmutableViewportMetrics viewportMetrics = getMetrics();
   viewportMetrics = viewportMetrics.scaleTo(zoomFactor, focus);
   mTarget.setViewportMetrics(viewportMetrics);
 }