/** * Creates a scale animation builder, that when started will animate a zoom in or out. If this would move the image * beyond the panning limits, the image is automatically panned during the animation. * @param scale Target scale. * @return {@link AnimationBuilder} instance. Call {@link SubsamplingScaleImageView.AnimationBuilder#start()} to start the anim. */ @Nullable public AnimationBuilder animateScale(float scale) { if (!isReady()) { return null; } return new AnimationBuilder(scale); }
/** * Creates a scale animation builder, that when started will animate a zoom in or out. If this would move the image * beyond the panning limits, the image is automatically panned during the animation. * @param scale Target scale. * @param sCenter Target source center. * @return {@link AnimationBuilder} instance. Call {@link SubsamplingScaleImageView.AnimationBuilder#start()} to start the anim. */ @Nullable public AnimationBuilder animateScaleAndCenter(float scale, PointF sCenter) { if (!isReady()) { return null; } return new AnimationBuilder(scale, sCenter); }
/** * Creates a panning animation builder, that when started will animate the image to place the given coordinates of * the image in the center of the screen. If doing this would move the image beyond the edges of the screen, the * image is instead animated to move the center point as near to the center of the screen as is allowed - it's * guaranteed to be on screen. * @param sCenter Target center point * @return {@link AnimationBuilder} instance. Call {@link SubsamplingScaleImageView.AnimationBuilder#start()} to start the anim. */ @Nullable public AnimationBuilder animateCenter(PointF sCenter) { if (!isReady()) { return null; } return new AnimationBuilder(sCenter); }
@Override public boolean onSingleTapConfirmed(MotionEvent e) { if (imageView.isReady()) { PointF sCoord = imageView.viewToSourceCoord(e.getX(), e.getY()); Toast.makeText(getApplicationContext(), "Single tap: " + ((int)sCoord.x) + ", " + ((int)sCoord.y), Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), "Single tap: Image not ready", Toast.LENGTH_SHORT).show(); } return true; } @Override
@Override public boolean onDoubleTap(MotionEvent e) { if (imageView.isReady()) { PointF sCoord = imageView.viewToSourceCoord(e.getX(), e.getY()); Toast.makeText(getApplicationContext(), "Double tap: " + ((int)sCoord.x) + ", " + ((int)sCoord.y), Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), "Double tap: Image not ready", Toast.LENGTH_SHORT).show(); } return true; } });
@Override public void onLongPress(MotionEvent e) { if (imageView.isReady()) { PointF sCoord = imageView.viewToSourceCoord(e.getX(), e.getY()); Toast.makeText(getApplicationContext(), "Long press: " + ((int)sCoord.x) + ", " + ((int)sCoord.y), Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), "Long press: Image not ready", Toast.LENGTH_SHORT).show(); } } @Override
/** * 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(); } }
/** * 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(); } }
/** * By default, image tiles are at least as high resolution as the screen. For a retina screen this may not be * necessary, and may increase the likelihood of an OutOfMemoryError. This method sets a DPI at which higher * resolution tiles should be loaded. Using a lower number will on average use less memory but result in a lower * quality image. 160-240dpi will usually be enough. This should be called before setting the image source, * because it affects which tiles get loaded. When using an untiled source image this method has no effect. * @param minimumTileDpi Tile loading threshold. */ public void setMinimumTileDpi(int minimumTileDpi) { DisplayMetrics metrics = getResources().getDisplayMetrics(); float averageDpi = (metrics.xdpi + metrics.ydpi)/2; this.minimumTileDpi = (int)Math.min(averageDpi, minimumTileDpi); if (isReady()) { reset(false); invalidate(); } }
/** * Fully zoom out and return the image to the middle of the screen. This might be useful if you have a view pager * and want images to be reset when the user has moved to another page. */ public final void resetScaleAndCenter() { this.anim = null; this.pendingScale = limitedScale(0); if (isReady()) { this.sPendingCenter = new PointF(sWidth()/2, sHeight()/2); } else { this.sPendingCenter = new PointF(0, 0); } invalidate(); }
/** * Calculate how much further the image can be panned in each direction. The results are set on * the supplied {@link RectF} and expressed as screen pixels. For example, if the image cannot be * panned any further towards the left, the value of {@link RectF#left} will be set to 0. * @param vTarget target object for results. Re-use for efficiency. */ public final void getPanRemaining(RectF vTarget) { if (!isReady()) { return; } float scaleWidth = scale * sWidth(); float scaleHeight = scale * sHeight(); if (panLimit == PAN_LIMIT_CENTER) { vTarget.top = Math.max(0, -(vTranslate.y - (getHeight() / 2))); vTarget.left = Math.max(0, -(vTranslate.x - (getWidth() / 2))); vTarget.bottom = Math.max(0, vTranslate.y - ((getHeight() / 2) - scaleHeight)); vTarget.right = Math.max(0, vTranslate.x - ((getWidth() / 2) - scaleWidth)); } else if (panLimit == PAN_LIMIT_OUTSIDE) { vTarget.top = Math.max(0, -(vTranslate.y - getHeight())); vTarget.left = Math.max(0, -(vTranslate.x - getWidth())); vTarget.bottom = Math.max(0, vTranslate.y + scaleHeight); vTarget.right = Math.max(0, vTranslate.x + scaleWidth); } else { vTarget.top = Math.max(0, -vTranslate.y); vTarget.left = Math.max(0, -vTranslate.x); vTarget.bottom = Math.max(0, (scaleHeight + vTranslate.y) - getHeight()); vTarget.right = Math.max(0, (scaleWidth + vTranslate.x) - getWidth()); } }
if (panLimit == PAN_LIMIT_OUTSIDE && isReady()) { center = false; float scaleHeight = scale * sHeight(); if (panLimit == PAN_LIMIT_CENTER && isReady()) { vTranslate.x = Math.max(vTranslate.x, getWidth()/2 - scaleWidth); vTranslate.y = Math.max(vTranslate.y, getHeight()/2 - scaleHeight); if (panLimit == PAN_LIMIT_CENTER && isReady()) { maxTx = Math.max(0, getWidth()/2); maxTy = Math.max(0, getHeight()/2);
/** * Enable or disable pan gesture detection. Disabling pan causes the image to be centered. Pan * can still be changed from code. * @param panEnabled true to enable panning, false to disable. */ public final void setPanEnabled(boolean panEnabled) { this.panEnabled = panEnabled; if (!panEnabled && vTranslate != null) { vTranslate.x = (getWidth()/2) - (scale * (sWidth()/2)); vTranslate.y = (getHeight()/2) - (scale * (sHeight()/2)); if (isReady()) { refreshRequiredTiles(true); invalidate(); } } }
/** * Creates a scale animation builder, that when started will animate a zoom in or out. If this would move the image * beyond the panning limits, the image is automatically panned during the animation. * @param scale Target scale. * @return {@link AnimationBuilder} instance. Call {@link SubsamplingScaleImageView.AnimationBuilder#start()} to start the anim. */ public AnimationBuilder animateScale(float scale) { if (!isReady()) { return null; } return new AnimationBuilder(scale); }
/** * Creates a scale animation builder, that when started will animate a zoom in or out. If this would move the image * beyond the panning limits, the image is automatically panned during the animation. * @param scale Target scale. * @return {@link AnimationBuilder} instance. Call {@link SubsamplingScaleImageView.AnimationBuilder#start()} to start the anim. */ public AnimationBuilder animateScaleAndCenter(float scale, PointF sCenter) { if (!isReady()) { return null; } return new AnimationBuilder(scale, sCenter); }
/** * Creates a panning animation builder, that when started will animate the image to place the given coordinates of * the image in the center of the screen. If doing this would move the image beyond the edges of the screen, the * image is instead animated to move the center point as near to the center of the screen as is allowed - it's * guaranteed to be on screen. * @param sCenter Target center point * @return {@link AnimationBuilder} instance. Call {@link SubsamplingScaleImageView.AnimationBuilder#start()} to start the anim. */ public AnimationBuilder animateCenter(PointF sCenter) { if (!isReady()) { return null; } return new AnimationBuilder(sCenter); }
/** * 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(); } }
/** * Fully zoom out and return the image to the middle of the screen. This might be useful if you have a view pager * and want images to be reset when the user has moved to another page. */ public final void resetScaleAndCenter() { this.anim = null; this.pendingScale = limitedScale(0); if (isReady()) { this.sPendingCenter = new PointF(sWidth()/2, sHeight()/2); } else { this.sPendingCenter = new PointF(0, 0); } invalidate(); }
/** * Enable or disable pan gesture detection. Disabling pan causes the image to be centered. */ public final void setPanEnabled(boolean panEnabled) { this.panEnabled = panEnabled; if (!panEnabled && vTranslate != null) { vTranslate.x = (getWidth()/2) - (scale * (sWidth()/2)); vTranslate.y = (getHeight()/2) - (scale * (sHeight()/2)); if (isReady()) { refreshRequiredTiles(true); invalidate(); } } }