public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (!canScroll()) { return false; } if (DEBUG) { Log.i(TAG, "onFling"); } if (Math.abs(velocityX) > (mMinFlingVelocity * 4) || Math.abs(velocityY) > (mMinFlingVelocity * 4)) { if (DEBUG) { Log.v(TAG, "velocity: " + velocityY); Log.v(TAG, "diff: " + (e2.getY() - e1.getY())); } final float scale = Math.min(Math.max(2f, getScale() / 2), 3.f); float scaledDistanceX = ((velocityX) / mMaxFlingVelocity) * (getWidth() * scale); float scaledDistanceY = ((velocityY) / mMaxFlingVelocity) * (getHeight() * scale); if (DEBUG) { Log.v(TAG, "scale: " + getScale() + ", scale_final: " + scale); Log.v(TAG, "scaledDistanceX: " + scaledDistanceX); Log.v(TAG, "scaledDistanceY: " + scaledDistanceY); } mUserScaled = true; double total = Math.sqrt(Math.pow(scaledDistanceX, 2) + Math.pow(scaledDistanceY, 2)); scrollBy(scaledDistanceX, scaledDistanceY, (long) Math.min(Math.max(300, total / 5), 800)); postInvalidate(); return true; } return false; }
@Override public boolean onScale(ScaleGestureDetector detector) { float span = detector.getCurrentSpan() - detector.getPreviousSpan(); float targetScale = getScale() * detector.getScaleFactor(); if (mScaleEnabled) { if (mScaled && span != 0) { mUserScaled = true; targetScale = Math.min(getMaxScale(), Math.max(targetScale, getMinScale() - MIN_SCALE_DIFF)); zoomTo(targetScale, detector.getFocusX(), detector.getFocusY()); mDoubleTapDirection = 1; invalidate(); return true; } // This is to prevent a glitch the first time // image is scaled. if (!mScaled) { mScaled = true; } } return true; }
@Override public boolean onDown(MotionEvent e) { if (DEBUG) { Log.i(TAG, "onDown"); } stopAllAnimations(); return ImageViewTouch.this.onDown(e); } }
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (!canScroll()) { return false; } mUserScaled = true; scrollBy(-distanceX, -distanceY); invalidate(); return true; }
public boolean onUp(MotionEvent e) { if (getBitmapChanged()) { return false; } if (getScale() < getMinScale()) { zoomTo(getMinScale(), 50); } return true; }
@Override protected void onZoomAnimationCompleted(float scale) { if (DEBUG) { Log.d(TAG, "onZoomAnimationCompleted. scale: " + scale + ", minZoom: " + getMinScale()); } if (scale < getMinScale()) { zoomTo(getMinScale(), 50); } }
@Override public boolean onDoubleTap(MotionEvent e) { if (DEBUG) { Log.i(TAG, "onDoubleTap. double tap enabled? " + mDoubleTapEnabled); } if (mDoubleTapEnabled) { if (Build.VERSION.SDK_INT >= 19) { if (mScaleDetector.isQuickScaleEnabled()) { return true; } } mUserScaled = true; float scale = getScale(); float targetScale; targetScale = onDoubleTapPost(scale, getMaxScale(), getMinScale()); targetScale = Math.min(getMaxScale(), Math.max(targetScale, getMinScale())); zoomTo(targetScale, e.getX(), e.getY(), mDefaultAnimationDuration); } if (null != mDoubleTapListener) { mDoubleTapListener.onDoubleTap(); } return super.onDoubleTap(e); }
@Override public void onDrawableChanged(final Drawable drawable) { Log.v(LOG_TAG, "image scale: " + mImage.getScale() + "/" + mImage.getMinScale()); Log.v(LOG_TAG, "scale type: " + mImage.getDisplayType() + "/" + mImage.getScaleType()); } }
/** * Determines whether this ImageViewTouch can be scrolled. * * @param direction - positive direction value means scroll from right to left, * negative value means scroll from left to right * @return true if there is some more place to scroll, false - otherwise. */ @SuppressWarnings ("unused") public boolean canScroll(int direction) { RectF bitmapRect = getBitmapRect(); updateRect(bitmapRect, mScrollPoint); Rect imageViewRect = new Rect(); getGlobalVisibleRect(imageViewRect); if (null == bitmapRect) { return false; } if (bitmapRect.right >= imageViewRect.right) { if (direction < 0) { return Math.abs(bitmapRect.right - imageViewRect.right) > SCROLL_DELTA_THRESHOLD; } } double bitmapScrollRectDelta = Math.abs(bitmapRect.left - mScrollPoint.x); return bitmapScrollRectDelta > SCROLL_DELTA_THRESHOLD; }
mImage.setDisplayType(DisplayType.FIT_IF_BIGGER); mImage.setSingleTapListener( new OnImageViewTouchSingleTapListener() { mImage.setDoubleTapListener( new OnImageViewTouchDoubleTapListener() { mImage.setOnDrawableChangedListener( new OnDrawableChangeListener() {
image.setDisplayType(ImageViewTouchBase.DisplayType.FIT_TO_SCREEN); image.setSingleTapListener(new ImageViewTouch.OnImageViewTouchSingleTapListener() { @Override public void onSingleTapConfirmed() {
@Override protected void onLayoutChanged(final int left, final int top, final int right, final int bottom) { super.onLayoutChanged(left, top, right, bottom); Log.v(TAG, "min: " + getMinScale() + ", max: " + getMaxScale() + ", result: " + (getMaxScale() - getMinScale()) / 2f); mScaleFactor = ((getMaxScale() - getMinScale()) / 2f) + 0.5f; }
public boolean canScroll() { if (getScale() > 1) { return true; } RectF bitmapRect = getBitmapRect(); return !mViewPort.contains(bitmapRect); }
@Override public boolean onTouchEvent(MotionEvent event) { if (getBitmapChanged()) { return false; } final int action = event.getActionMasked(); if (action == MotionEvent.ACTION_POINTER_UP) { mPointerUpTime = event.getEventTime(); } mScaleDetector.onTouchEvent(event); if (!mScaleDetector.isInProgress()) { mGestureDetector.onTouchEvent(event); } switch (action) { case MotionEvent.ACTION_UP: return onUp(event); default: break; } return true; }
@Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (!mScrollEnabled) { return false; } if (e1 == null || e2 == null) { return false; } if (e1.getPointerCount() > 1 || e2.getPointerCount() > 1) { return false; } if (mScaleDetector.isInProgress()) { return false; } return ImageViewTouch.this.onScroll(e1, e2, distanceX, distanceY); }
@Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { //if (!mScrollEnabled) return false; if (e1.getPointerCount() > 1 || e2.getPointerCount() > 1) return false; if (mScaleDetector.isInProgress()) return false; if (getScale() == 1f) return false; return ImageViewTouch.this.onFling(e1, e2, velocityX, velocityY); }
@Override public void onClick(View v) { int current = mImage.getDisplayType().ordinal() + 1; if (current >= DisplayType.values().length) { current = 0; } mImage.setDisplayType(DisplayType.values()[current]); } }
@Override protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { if (v instanceof ImageViewTouch) { return ((ImageViewTouch) v).canScroll(dx) || super.canScroll(v, checkV, dx, x, y); } return super.canScroll(v, checkV, dx, x, y); } }
@Override public float getMaxScale() { return Math.max(2f, super.getMaxScale()); }
@Override public boolean onDown(MotionEvent e) { return ImageViewTouch.this.onDown(e); } }