/** * Set the minimum scale type. See static fields. Normally {@link #SCALE_TYPE_CENTER_INSIDE} is best, for image galleries. * @param scaleType a scale type constant. See static fields. */ public final void setMinimumScaleType(int scaleType) { if (!VALID_SCALE_TYPES.contains(scaleType)) { throw new IllegalArgumentException("Invalid scale type: " + scaleType); } this.minimumScaleType = scaleType; if (isReady()) { fitToBounds(true); invalidate(); } }
/** * Set the pan limiting style. See static fields. Normally {@link #PAN_LIMIT_INSIDE} is best, for image galleries. * @param panLimit a pan limit constant. See static fields. */ public final void setPanLimit(int panLimit) { if (!VALID_PAN_LIMITS.contains(panLimit)) { throw new IllegalArgumentException("Invalid pan limit: " + panLimit); } this.panLimit = panLimit; if (isReady()) { fitToBounds(true); invalidate(); } }
/** * Adjusts current scale and translate values to keep scale within the allowed range and the image on screen. Minimum scale * is set so one dimension fills the view and the image is centered on the other dimension. * @param center Whether the image should be centered in the dimension it's too small to fill. While animating this can be false to avoid changes in direction as bounds are reached. */ private void fitToBounds(boolean center) { boolean init = false; if (vTranslate == null) { init = true; vTranslate = new PointF(0, 0); } if (satTemp == null) { satTemp = new ScaleAndTranslate(0, new PointF(0, 0)); } satTemp.scale = scale; satTemp.vTranslate.set(vTranslate); fitToBounds(center, satTemp); scale = satTemp.scale; vTranslate.set(satTemp.vTranslate); if (init && minimumScaleType != SCALE_TYPE_START) { vTranslate.set(vTranslateForSCenter(sWidth()/2, sHeight()/2, scale)); } }
/** * Sets scale and translate ready for the next draw. */ private void preDraw() { if (getWidth() == 0 || getHeight() == 0 || sWidth <= 0 || sHeight <= 0) { return; } // If waiting to translate to new center position, set translate now if (sPendingCenter != null && pendingScale != null) { scale = pendingScale; if (vTranslate == null) { vTranslate = new PointF(); } vTranslate.x = (getWidth()/2) - (scale * sPendingCenter.x); vTranslate.y = (getHeight()/2) - (scale * sPendingCenter.y); sPendingCenter = null; pendingScale = null; fitToBounds(true); refreshRequiredTiles(true); } // On first display of base image set up position, and in other cases make sure scale is correct. fitToBounds(false); }
/** * Get the translation required to place a given source coordinate at the center of the screen, with the center * adjusted for asymmetric padding. Accepts the desired scale as an argument, so this is independent of current * translate and scale. The result is fitted to bounds, putting the image point as near to the screen center as permitted. */ @NonNull private PointF vTranslateForSCenter(float sCenterX, float sCenterY, float scale) { int vxCenter = getPaddingLeft() + (getWidth() - getPaddingRight() - getPaddingLeft())/2; int vyCenter = getPaddingTop() + (getHeight() - getPaddingBottom() - getPaddingTop())/2; if (satTemp == null) { satTemp = new ScaleAndTranslate(0, new PointF(0, 0)); } satTemp.scale = scale; satTemp.vTranslate.set(vxCenter - (sCenterX * scale), vyCenter - (sCenterY * scale)); fitToBounds(true, satTemp); return satTemp.vTranslate; }
vTranslate.y = vCenterEndY - vTopNow; if ((previousScale * sHeight() < getHeight() && scale * sHeight() >= getHeight()) || (previousScale * sWidth() < getWidth() && scale * sWidth() >= getWidth())) { fitToBounds(true); vCenterStart.set(vCenterEndX, vCenterEndY); vTranslateStart.set(vTranslate); fitToBounds(true); refreshRequiredTiles(eagerLoadingEnabled); vTranslate.y = vCenterStart.y - vTopNow; if ((previousScale * sHeight() < getHeight() && scale * sHeight() >= getHeight()) || (previousScale * sWidth() < getWidth() && scale * sWidth() >= getWidth())) { fitToBounds(true); vCenterStart.set(sourceToViewCoord(quickScaleSCenter)); vTranslateStart.set(vTranslate); fitToBounds(true); refreshRequiredTiles(eagerLoadingEnabled); fitToBounds(true); boolean atXEdge = lastX != vTranslate.x; boolean atYEdge = lastY != vTranslate.y;
fitToBounds(finished || (anim.scaleStart == anim.scaleEnd)); sendStateChanged(scaleBefore, vTranslateBefore, anim.origin); refreshRequiredTiles(finished);
fitToBounds(true, satTemp);
/** * Set the pan limiting style. See static fields. Normally {@link #PAN_LIMIT_INSIDE} is best, for image galleries. */ public final void setPanLimit(int panLimit) { if (!VALID_PAN_LIMITS.contains(panLimit)) { throw new IllegalArgumentException("Invalid pan limit: " + panLimit); } this.panLimit = panLimit; if (isReady()) { fitToBounds(true); invalidate(); } }
/** * Set the minimum scale type. See static fields. Normally {@link #SCALE_TYPE_CENTER_INSIDE} is best, for image galleries. */ public final void setMinimumScaleType(int scaleType) { if (!VALID_SCALE_TYPES.contains(scaleType)) { throw new IllegalArgumentException("Invalid scale type: " + scaleType); } this.minimumScaleType = scaleType; if (isReady()) { fitToBounds(true); invalidate(); } }
/** * Adjusts current scale and translate values to keep scale within the allowed range and the image on screen. Minimum scale * is set so one dimension fills the view and the image is centered on the other dimension. * @param center Whether the image should be centered in the dimension it's too small to fill. While animating this can be false to avoid changes in direction as bounds are reached. */ private void fitToBounds(boolean center) { boolean init = false; if (vTranslate == null) { init = true; vTranslate = new PointF(0, 0); } if (satTemp == null) { satTemp = new ScaleAndTranslate(0, new PointF(0, 0)); } satTemp.scale = scale; satTemp.vTranslate.set(vTranslate); fitToBounds(center, satTemp); scale = satTemp.scale; vTranslate.set(satTemp.vTranslate); if (init) { vTranslate.set(vTranslateForSCenter(sWidth()/2, sHeight()/2, scale)); } }
/** * Sets scale and translate ready for the next draw. */ private void preDraw() { if (getWidth() == 0 || getHeight() == 0 || sWidth <= 0 || sHeight <= 0) { return; } // If waiting to translate to new center position, set translate now if (sPendingCenter != null && pendingScale != null) { scale = pendingScale; if (vTranslate == null) { vTranslate = new PointF(); } vTranslate.x = (getWidth()/2) - (scale * sPendingCenter.x); vTranslate.y = (getHeight()/2) - (scale * sPendingCenter.y); sPendingCenter = null; pendingScale = null; fitToBounds(true); refreshRequiredTiles(true); } // On first display of base image set up position, and in other cases make sure scale is correct. fitToBounds(false); }
/** * Get the translation required to place a given source coordinate at the center of the screen, with the center * adjusted for asymmetric padding. Accepts the desired scale as an argument, so this is independent of current * translate and scale. The result is fitted to bounds, putting the image point as near to the screen center as permitted. */ private PointF vTranslateForSCenter(float sCenterX, float sCenterY, float scale) { int vxCenter = getPaddingLeft() + (getWidth() - getPaddingRight() - getPaddingLeft())/2; int vyCenter = getPaddingTop() + (getHeight() - getPaddingBottom() - getPaddingTop())/2; if (satTemp == null) { satTemp = new ScaleAndTranslate(0, new PointF(0, 0)); } satTemp.scale = scale; satTemp.vTranslate.set(vxCenter - (sCenterX * scale), vyCenter - (sCenterY * scale)); fitToBounds(true, satTemp); return satTemp.vTranslate; }
fitToBounds(finished || (anim.scaleStart == anim.scaleEnd)); sendStateChanged(scaleBefore, vTranslateBefore, anim.origin); refreshRequiredTiles(finished);
vTranslate.y = vCenterEndY - vTopNow; if ((previousScale * sHeight() < getHeight() && scale * sHeight() >= getHeight()) || (previousScale * sWidth() < getWidth() && scale * sWidth() >= getWidth())) { fitToBounds(true); vCenterStart.set(vCenterEndX, vCenterEndY); vTranslateStart.set(vTranslate); fitToBounds(true); refreshRequiredTiles(false); vTranslate.y = vCenterStart.y - vTopNow; if ((previousScale * sHeight() < getHeight() && scale * sHeight() >= getHeight()) || (previousScale * sWidth() < getWidth() && scale * sWidth() >= getWidth())) { fitToBounds(true); vCenterStart.set(sourceToViewCoord(quickScaleSCenter)); vTranslateStart.set(vTranslate); fitToBounds(true); refreshRequiredTiles(false); fitToBounds(true); boolean atXEdge = lastX != vTranslate.x; boolean atYEdge = lastY != vTranslate.y;
fitToBounds(true, satTemp);