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.

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>