Code example for ImageView

Methods: getDrawablesetImageMatrix, getHeight, getParent, getWidth

0
				final RectF displayRect = getDisplayRect();
 
				if (null != displayRect) {
					final float x = e.getX(), y = e.getY();
 
					// Check to see if the user tapped on the photo 
					if (displayRect.contains(x, y)) {
 
						float xResult = (x - displayRect.left) / displayRect.width();
						float yResult = (y - displayRect.top) / displayRect.height();
 
						mPhotoTapListener.onPhotoTap(imageView, xResult, yResult);
						return true; 
					} 
				} 
			} 
			if (null != mViewTapListener) {
				mViewTapListener.onViewTap(imageView, e.getX(), e.getY());
			} 
		} 
 
		return false; 
	} 
 
	@Override 
	public final boolean onTouch(View v, MotionEvent ev) {
		boolean handled = false;
 
		if (mZoomEnabled) {
			switch (ev.getAction()) {
				case MotionEvent.ACTION_DOWN:
					// First, disable the Parent from intercepting the touch 
					// event 
					v.getParent().requestDisallowInterceptTouchEvent(true);
 
					// If we're flinging, and the user presses down, cancel 
					// fling 
					cancelFling(); 
					break; 
 
				case MotionEvent.ACTION_CANCEL:
				case MotionEvent.ACTION_UP:
					// If the user has zoomed less than min scale, zoom back 
					// to min scale 
					if (getScale() < mMinScale) {
						RectF rect = getDisplayRect();
						if (null != rect) {
							v.post(new AnimatedZoomRunnable(getScale(), mMinScale, rect.centerX(), rect.centerY()));
							handled = true;
						} 
					} 
					break; 
			} 
 
			// Check to see if the user double tapped 
			if (null != mGestureDetector && mGestureDetector.onTouchEvent(ev)) {
				handled = true;
			} 
 
			// Finally, try the Scale/Drag detector 
			if (null != mScaleDragDetector && mScaleDragDetector.onTouchEvent(ev)) {
				handled = true;
			} 
		} 
 
		return handled;
	} 
 
    @Override 
    public void setAllowParentInterceptOnEdge(boolean allow) {
        mAllowParentInterceptOnEdge = allow;
    } 
 
	@Override 
	public void setMinScale(float minScale) {
		checkZoomLevels(minScale, mMidScale, mMaxScale);
		mMinScale = minScale;
	} 
 
	@Override 
	public void setMidScale(float midScale) {
		checkZoomLevels(mMinScale, midScale, mMaxScale);
		mMidScale = midScale;
	} 
 
	@Override 
	public void setMaxScale(float maxScale) {
		checkZoomLevels(mMinScale, mMidScale, maxScale);
		mMaxScale = maxScale;
	} 
 
	@Override 
	public final void setOnLongClickListener(OnLongClickListener listener) {
		mLongClickListener = listener;
	} 
 
	@Override 
	public final void setOnMatrixChangeListener(OnMatrixChangedListener listener) {
		mMatrixChangeListener = listener;
	} 
 
	@Override 
	public final void setOnPhotoTapListener(OnPhotoTapListener listener) {
		mPhotoTapListener = listener;
	} 
 
	@Override 
	public final void setOnViewTapListener(OnViewTapListener listener) {
		mViewTapListener = listener;
	} 
 
	@Override 
	public final void setScaleType(ScaleType scaleType) {
		if (isSupportedScaleType(scaleType) && scaleType != mScaleType) {
			mScaleType = scaleType;
 
			// Finally update 
			update(); 
		} 
	} 
 
	@Override 
	public final void setZoomable(boolean zoomable) {
		mZoomEnabled = zoomable;
		update(); 
	} 
 
	public final void update() { 
		ImageView imageView = getImageView();
 
		if (null != imageView) {
			if (mZoomEnabled) {
				// Make sure we using MATRIX Scale Type 
				setImageViewScaleTypeMatrix(imageView);
 
				// Update the base matrix using the current drawable 
				updateBaseMatrix(imageView.getDrawable());
			} else { 
				// Reset the Matrix... 
				resetMatrix(); 
			} 
		} 
	} 
 
	@Override 
	public final void zoomTo(float scale, float focalX, float focalY) {
		ImageView imageView = getImageView();
 
		if (null != imageView) {
			imageView.post(new AnimatedZoomRunnable(getScale(), scale, focalX, focalY));
		} 
	} 
 
	protected Matrix getDisplayMatrix() {
		mDrawMatrix.set(mBaseMatrix);
		mDrawMatrix.postConcat(mSuppMatrix);
		return mDrawMatrix;
	} 
 
	private void cancelFling() { 
		if (null != mCurrentFlingRunnable) {
			mCurrentFlingRunnable.cancelFling();
			mCurrentFlingRunnable = null;
		} 
	} 
 
	/** 
	 * Helper method that simply checks the Matrix, and then displays the result 
	 */ 
	private void checkAndDisplayMatrix() { 
		checkMatrixBounds(); 
		setImageViewMatrix(getDisplayMatrix()); 
	} 
 
	private void checkImageViewScaleType() { 
		ImageView imageView = getImageView();
 
		/** 
		 * PhotoView's getScaleType() will just divert to this.getScaleType() so 
		 * only call if we're not attached to a PhotoView. 
		 */ 
		if (null != imageView && !(imageView instanceof PhotoView)) {
			if (imageView.getScaleType() != ScaleType.MATRIX) {
				throw new IllegalStateException(
						"The ImageView's ScaleType has been changed since attaching a PhotoViewAttacher"); 
			} 
		} 
	} 
 
	private void checkMatrixBounds() { 
		final ImageView imageView = getImageView();
		if (null == imageView) {
			return; 
		} 
 
		final RectF rect = getDisplayRect(getDisplayMatrix());
		if (null == rect) {
			return; 
		} 
 
		final float height = rect.height(), width = rect.width();
		float deltaX = 0, deltaY = 0;
 
		final int viewHeight = imageView.getHeight();
		if (height <= viewHeight) {
			switch (mScaleType) {
				case FIT_START:
					deltaY = -rect.top;
					break; 
				case FIT_END:
					deltaY = viewHeight - height - rect.top;
					break; 
				default: 
					deltaY = (viewHeight - height) / 2 - rect.top;
					break; 
			} 
		} else if (rect.top > 0) {
			deltaY = -rect.top;
		} else if (rect.bottom < viewHeight) {
			deltaY = viewHeight - rect.bottom;
		} 
 
		final int viewWidth = imageView.getWidth();
		if (width <= viewWidth) {
			switch (mScaleType) {
				case FIT_START:
					deltaX = -rect.left;
					break; 
				case FIT_END:
					deltaX = viewWidth - width - rect.left;
					break; 
				default: 
					deltaX = (viewWidth - width) / 2 - rect.left;
					break; 
			} 
			mScrollEdge = EDGE_BOTH;
		} else if (rect.left > 0) {
			mScrollEdge = EDGE_LEFT;
			deltaX = -rect.left;
		} else if (rect.right < viewWidth) {
			deltaX = viewWidth - rect.right;
			mScrollEdge = EDGE_RIGHT;
		} else { 
			mScrollEdge = EDGE_NONE;
		} 
 
		// Finally actually translate the matrix 
		mSuppMatrix.postTranslate(deltaX, deltaY);
	} 
 
	/** 
	 * Helper method that maps the supplied Matrix to the current Drawable 
	 *  
	 * @param matrix - Matrix to map Drawable against 
	 * @return RectF - Displayed Rectangle 
	 */ 
	private RectF getDisplayRect(Matrix matrix) {
		ImageView imageView = getImageView();
 
		if (null != imageView) {
			Drawable d = imageView.getDrawable();
			if (null != d) {
				mDisplayRect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
				matrix.mapRect(mDisplayRect);
				return mDisplayRect;
			} 
		} 
		return null; 
	} 
 
	/** 
	 * Helper method that 'unpacks' a Matrix and returns the required value 
	 *  
	 * @param matrix - Matrix to unpack 
	 * @param whichValue - Which value from Matrix.M* to return 
	 * @return float - returned value 
	 */ 
	private float getValue(Matrix matrix, int whichValue) {
		matrix.getValues(mMatrixValues);
		return mMatrixValues[whichValue];
	} 
 
	/** 
	 * Resets the Matrix back to FIT_CENTER, and then displays it.s 
	 */ 
	private void resetMatrix() { 
		mSuppMatrix.reset();
		setImageViewMatrix(getDisplayMatrix()); 
		checkMatrixBounds(); 
	} 
 
	private void setImageViewMatrix(Matrix matrix) {
		ImageView imageView = getImageView();
		if (null != imageView) {
 
			checkImageViewScaleType(); 
			imageView.setImageMatrix(matrix);
 
			// Call MatrixChangedListener if needed 
			if (null != mMatrixChangeListener) {
				RectF displayRect = getDisplayRect(matrix);
				if (null != displayRect) {
					mMatrixChangeListener.onMatrixChanged(displayRect);
				} 
			} 
		} 
	} 
 
	/** 
	 * Calculate Matrix for FIT_CENTER 
	 *  
	 * @param d - Drawable being displayed 
	 */ 
	private void updateBaseMatrix(Drawable d) {
		ImageView imageView = getImageView();
		if (null == imageView || null == d) {
			return; 
		} 
 
		final float viewWidth = imageView.getWidth();
		final float viewHeight = imageView.getHeight();
		final int drawableWidth = d.getIntrinsicWidth();
		final int drawableHeight = d.getIntrinsicHeight();
 
		mBaseMatrix.reset();
 
		final float widthScale = viewWidth / drawableWidth;
		final float heightScale = viewHeight / drawableHeight;
 
		if (mScaleType == ScaleType.CENTER) {
			mBaseMatrix.postTranslate((viewWidth - drawableWidth) / 2F, (viewHeight - drawableHeight) / 2F);
 
		} else if (mScaleType == ScaleType.CENTER_CROP) {
			float scale = Math.max(widthScale, heightScale);
			mBaseMatrix.postScale(scale, scale);
			mBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F,
					(viewHeight - drawableHeight * scale) / 2F);
 
		} else if (mScaleType == ScaleType.CENTER_INSIDE) {
			float scale = Math.min(1.0f, Math.min(widthScale, heightScale));
			mBaseMatrix.postScale(scale, scale);
			mBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F,
					(viewHeight - drawableHeight * scale) / 2F);
 
		} else { 
			RectF mTempSrc = new RectF(0, 0, drawableWidth, drawableHeight);
			RectF mTempDst = new RectF(0, 0, viewWidth, viewHeight);
 
			switch (mScaleType) {
				case FIT_CENTER:
					mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.CENTER);