Search code examples
androidimageviewtouchzoomingpan

TouchImageView set drag and zoom bounds limits , prevent from going off screen


I have a crop activity and an imageview behind drawable rectangle, i have set a touch method to zoom and drag the imageview but the problem is that i can drag it off screen and zoom in and out off screen, i want to set limits for the drag and zoom so it fits my rectangle which is a square width and height are the same.

i have tried many different types of code but still it doesn't get to work , i need also to handle images that are wider , not just square or vertical images.

(please help me resolve this without any libraries, i am not allowed to use any)

Here is my code :

@Override
public boolean onTouch(View v, MotionEvent event) {

     ImageView view = (ImageView) v;

      // Dump touch event to log
      dumpEvent(event);

      // Handle touch events here...
      switch (event.getAction() & MotionEvent.ACTION_MASK) {
      case MotionEvent.ACTION_DOWN:
         savedMatrix.set(matrix);
         start.set(event.getX(), event.getY());
         Log.d(TAG, "mode=DRAG");
         mode = DRAG;
         break;

      case MotionEvent.ACTION_POINTER_DOWN:
         oldDist = spacing(event);
         Log.d(TAG, "oldDist=" + oldDist);

         if (oldDist > 10f) {

            savedMatrix.set(matrix);
            midPoint(mid, event);
            mode = ZOOM;
            Log.d(TAG, "mode=ZOOM");
         }
         break;



      case MotionEvent.ACTION_POINTER_UP:
         mode = NONE;
         Log.d(TAG, "mode=NONE");
         break;
          case MotionEvent.ACTION_UP:

          case MotionEvent.ACTION_MOVE:
         if (mode == DRAG) {

            matrix.set(savedMatrix);

            matrix.postTranslate(event.getX()  - start.x /(1.0f) ,
                 event.getY() - start.y / (1.0f) );


         }
         else if (mode == ZOOM) {
            float[] f = new float[9];

            float newDist = spacing(event);
            Log.d(TAG, "newDist=" + newDist);

            if (newDist > 10f) {
               matrix.set(savedMatrix);
               float scale = newDist / oldDist;
               matrix.postScale(scale, scale, mid.x, mid.y);
            }

             matrix.getValues(f);
             scaleX = f[Matrix.MSCALE_X];
             scaleY = f[Matrix.MSCALE_Y];


             if(scaleX <= 0.9f) {
                matrix.postScale((0.9f) / scaleX, (0.9f) /scaleY, mid.x, mid.y);
            }
            else if(scaleX >= 2.5f) {
                   matrix.postScale((2.5f)/scaleX, (2.5f)/scaleY, mid.x, mid.y);             
       } 


      }

         break;


      }

      view.setImageMatrix(matrix);
      return true; 
   }

Solution

  • public boolean onTouch(View v, MotionEvent event) {
            int action = event.getAction();
    
            DisplayMetrics displaymetrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
            int sH = displaymetrics.heightPixels;
            int sW = displaymetrics.widthPixels;
            float dx, dy, newX, newY;
    
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    dx = event.getRawX() - v.getX();
                    dy = event.getRawY() - v.getY();
                    break;
    
                case MotionEvent.ACTION_MOVE:
                    newX = event.getRawX() - dx;
                    newY = event.getRawY() - dy;
    
                    if ((newX <= 0 || newX >= sW-v.getWidth()) || (newY <= 0 || newY >= sH-v.getHeight()))
                        break;
    
                    v.setX(newX);
                    v.setY(newY);
                    break;
    
                case MotionEvent.ACTION_UP:
                    break;
    
                case MotionEvent.ACTION_CANCEL:
                    break;
    
                default:
                    break;
            }
    
            return true;
        }