Android image viewer setting panning bounds
The android image viewer setting panning bounds tutorial describes how to fix a couple of the main issues from the previous tutorial.
Which are
- The location of the previous pan is not saved which is causing a jittering affect.
- No limits have been set to panning to the end of the image, therefore the areas outside of the image can also be panned.
This android tutorial will describe how to resolve both of those issues. Starting with saving the location of the previous pan. And then setting panning limits which match the boundaries of the image.
Get Code
The code can be found on github from the following instructions below
https://github.com/mobapptuts/android_image_viewer.git Tag
image-viewer-pan-fixes
or you can run this command
git clone https://github.com/mobapptuts/android_image_viewer.git –branch
image-viewer-pan-fixes
Code Samples
Saving the coordinates of the previous pan
Create two members for saving the X & Y coordinates of the previous pan
private float mPreviousTranslateX = 0; private float mPreviousTranslateY = 0;
In the onTouchEvent saved the coordinates on the action up & use the previous coordinates on the action down
@Override public boolean onTouchEvent(MotionEvent event) { switch(event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mEventState = PAN; mStartX = event.getX() - mPreviousTranslateX; mStartY = event.getY() - mPreviousTranslateY; break; case MotionEvent.ACTION_UP: mEventState = NONE; mPreviousTranslateX = mTranslateX; mPreviousTranslateY = mTranslateY; break; case MotionEvent.ACTION_MOVE: mTranslateX = event.getX() - mStartX; mTranslateY = event.getY() - mStartY; break; case MotionEvent.ACTION_POINTER_DOWN: mEventState = ZOOM; break; } mScaleGestureDetector.onTouchEvent(event); if((mEventState == PAN && mScaleFactor != mMinZoom) || mEventState == ZOOM) { invalidate(); requestLayout(); } return true; }
Setting Panning Limits
We implement the control on the boundary limits in the custom view’s onDraw method.
Setting the minimum boundaries for left & top
As you can see below working out the extreme left & top positions is straight forward. Both positions ensure that the translate X & Y values never pass below 0.
if((mTranslateX * -1) < 0) { mTranslateX = 0; } if((mTranslateY * -1) < 0) { mTranslateY = 0; }
Setting the minimum boundaries for right & bottom
To work out the right & bottom values is slightly more complex. To start of two things we must visualise are the bitmap dimensions and how they are viewed from the display screen dimensions.
If we were to pan to the furtherest right & bottom positions of the bitmap, that would match the right & bottom values of the display screen. Which means the display screen left & top positions are calculated by removing the display width & height. Which are provided by the custom image view’s getWidth() & getHeight() methods.
else if ((mTranslateX * -1) > mImageWidth * mScaleFactor - getWidth()) { mTranslateX = (mImageWidth * mScaleFactor - getWidth()) * -1; } else if ((mTranslateY * -1) > mImageHeight * mScaleFactor - getHeight()) { mTranslateY = (mImageHeight * mScaleFactor - getHeight()) * -1; }
And here is the entire onDraw method
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.scale(mScaleFactor, mScaleFactor); // canvas.scale(mScaleFactor, mScaleFactor, mScaleGestureDetector.getFocusX(), mScaleGestureDetector.getFocusY()); if((mTranslateX * -1) < 0) { mTranslateX = 0; } else if ((mTranslateX * -1) > mImageWidth * mScaleFactor - getWidth()) { mTranslateX = (mImageWidth * mScaleFactor - getWidth()) * -1; } if((mTranslateY * -1) < 0) { mTranslateY = 0; } else if ((mTranslateY * -1) > mImageHeight * mScaleFactor - getHeight()) { mTranslateY = (mImageHeight * mScaleFactor - getHeight()) * -1; } canvas.translate(mTranslateX/mScaleFactor, mTranslateY/mScaleFactor); canvas.drawBitmap(mBitmap, 0, 0, null); canvas.restore(); }
Android image viewer setting panning bounds summary
In the android image viewer setting panning bounds tutorial we learned how to a ensure the display screen stayed within the image’s estate.
And how to remove the jitter when panning. By saving the coordinates from the previous pan so it can be calculated into the following pan.
This episode of the android image viewer tutorial demonstrates some of the enhancements required for implementing a polished panning solution. But this episode will be the conclusion of the android image viewer tutorial series.
If developers require a polished pinch, zoom & pan solution I’d recommend using a third party android library.