Finding and moving Bitmaps after canvas scale

Problems with Canvas, OpenGL, etc...

Finding and moving Bitmaps after canvas scale

Postby rensu » Tue Apr 30, 2013 10:29 am

So I have a canvas that I draw a bitmap onto.. When the scalefactor of the canvas is 1.0f everything works perfectly how I want it to.. However the problem is when I change the scale of the canvas. Either zoomed in or out I run into problems with the coordinates and finding the bitmap so I can move it on touch..

I've tried dividing coordinates by the scalefactor.. multiplying.. I just can't work out the right calculation to get my desired result! Please help!

Here is my code

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public void onDraw(Canvas canvas) {
  2.     // Log.v(TAG, "onDraw()");
  3.     clipBounds = canvas.getClipBounds();
  4.     if (bitmap == null) {
  5.         Log.w(TAG, "nothing to draw - bitmap is null");
  6.         super.onDraw(canvas);
  7.         return;
  8.     }
  9.  
  10.     if (firstDraw && (bitmap.getHeight() > 0) && (bitmap.getWidth() > 0)) {
  11.         // Don't let the user zoom out so much that the image is smaller
  12.         // than its containing frame
  13.         float minXScaleFactor = (float) viewWidth
  14.                 / (float) bitmap.getWidth();
  15.         float minYScaleFactor = (float) viewHeight
  16.                 / (float) bitmap.getHeight();
  17.         minScaleFactor = Math.max(minXScaleFactor, minYScaleFactor);
  18.         Log.d(TAG, "minScaleFactor: " + minScaleFactor);
  19.         // mScaleFactor = minScaleFactor; //start out "zoomed out" all the
  20.         // way
  21.  
  22.         mPosX = mPosY = 0;
  23.         firstDraw = false;
  24.     }
  25.     mScaleFactor = Math.max(mScaleFactor, minScaleFactor);
  26.  
  27.     canvasHeight = canvas.getHeight();
  28.     canvasWidth = canvas.getWidth();
  29.     // Log.d(TAG, "canvas density: " + canvas.getDensity() +
  30.     // " bitmap density: " + bitmap.getDensity());
  31.  
  32.     // Log.d(TAG, "mScaleFactor: " + mScaleFactor);
  33.  
  34.     // Save the canvas without translating (panning) or scaling (zooming)
  35.     // After each change, restore to this state, instead of compounding
  36.     // changes upon changes
  37.     canvas.save();
  38.     int maxX, minX, maxY, minY;
  39.     // Regardless of the screen density (HDPI, MDPI) or the scale factor,
  40.     // The image always consists of bitmap width divided by 2 pixels. If an
  41.     // image
  42.     // is 200 pixels wide and you scroll right 100 pixels, you just scrolled
  43.     // the image
  44.     // off the screen to the left.
  45.     minX = (int) (((viewWidth / mScaleFactor) - bitmap.getWidth()) / 2);
  46.     maxX = 0;
  47.     // How far can we move the image vertically without having a gap between
  48.     // image and frame?
  49.     minY = (int) (((viewHeight / mScaleFactor) - bitmap.getHeight()) / 2);
  50.     maxY = 0;
  51.     // Log.d(TAG, "minX: " + minX + " maxX: " + maxX + " minY: " + minY
  52.     // + " maxY: " + maxY);
  53.     // Do not go beyond the boundaries of the image
  54.     if (mPosX > maxX) {
  55.         mPosX = maxX;
  56.     }
  57.     if (mPosX < minX) {
  58.         mPosX = minX;
  59.     }
  60.     if (mPosY > maxY) {
  61.         mPosY = maxY;
  62.     }
  63.     if (mPosY < minY) {
  64.         mPosY = minY;
  65.     }
  66.  
  67.     canvas.scale(mScaleFactor, mScaleFactor);
  68.     // canvas.scale(0.6f, 0.6f);
  69.     // Log.i("","mPos " + mPosX);
  70.     canvas.translate(mPosX, mPosY);
  71.  
  72.     canvas.drawBitmap(bitmap, mPosX, mPosY, null);
  73.     canvas.drawBitmap(bmp, bPosX + mPosX, bPosY + mPosY, null);
  74.  
  75.     if (!firstDraw) {
  76.         bitmapCanvas.drawBitmap(bitmap, mPosX, mPosY, null);
  77.         bitmapCanvas.drawBitmap(bmp, bPosX + mPosX, bPosY + mPosY, null);
  78.     }
  79.  
  80.     super.onDraw(canvas);
  81.  
  82.     canvas.restore(); // clear translation/scaling
  83. }
  84.  
  85. @Override
  86. public boolean onTouchEvent(MotionEvent ev) {
  87.     // Let the ScaleGestureDetector inspect all events.
  88.     if (zoomEnabled) {
  89.         mScaleDetector.onTouchEvent(ev);
  90.     }
  91.  
  92.     if (panEnabled) {
  93.         final int action = ev.getAction();
  94.         switch (action & MotionEvent.ACTION_MASK) {
  95.  
  96.         case MotionEvent.ACTION_DOWN: {
  97.             final float x = ev.getX();
  98.             final float y = ev.getY();
  99.  
  100.             mLastTouchX = x;
  101.             mLastTouchY = y;
  102.  
  103.             mActivePointerId = ev.getPointerId(0);
  104.  
  105.             int mx = (int) mPosX * -1;
  106.             int my = (int) mPosY * -1;
  107.  
  108.             // int checkPointX = (int) (x + mx * 2);
  109.             // int checkPointY = (int) (y + my * 2);
  110.  
  111.             int checkPointX = (int) (x + mx * 2);
  112.             int checkPointY = (int) (y + my * 2);
  113.  
  114.             Log.i("ZOOMS", "ScaleFactor " + mScaleFactor);
  115.             Log.i("TOUCH COORD", "x " + checkPointX + " y " + checkPointY);
  116.             Log.i("BMP POS", "x " + bPosX + " bw " + (bPosX + bmp.getWidth()) + " y " + bPosY + " yw " + (bPosY + bmp.getHeight()));
  117.  
  118.             if (checkPointX > bPosX
  119.                     && checkPointX <= bPosX + bmp.getWidth()
  120.                     && checkPointY >= bPosY
  121.                     && checkPointY <= bPosY + bmp.getHeight())
  122.                 bitmapFound = true;
  123.             else
  124.                 bitmapFound = false;
  125.  
  126.             // if(mx > bmp.)
  127.             break;
  128.         }
  129.  
  130.         case MotionEvent.ACTION_MOVE: {
  131.             final int pointerIndex = ev.findPointerIndex(mActivePointerId);
  132.             final float x = ev.getX(pointerIndex);
  133.             final float y = ev.getY(pointerIndex);
  134.  
  135.             // Only move if the ScaleGestureDetector isn't processing a
  136.             // gesture.
  137.             if (!mScaleDetector.isInProgress()) {
  138.                 if (bitmapFound) {
  139.                     int mx = (int) mPosX * -1;
  140.                     int my = (int) mPosY * -1;
  141.  
  142.                     int checkPointX = (int) (x + mx * 2);
  143.                     int checkPointY = (int) (y + my * 2);
  144.  
  145.                     moveBitmap(checkPointX, checkPointY);
  146.                 } else
  147.                     moveCanvas(x, y);
  148.  
  149.                 invalidate();
  150.             }
  151.             mLastTouchX = x;
  152.             mLastTouchY = y;
  153.  
  154.             break;
  155.         }
  156.  
  157.         case MotionEvent.ACTION_UP: {
  158.             mActivePointerId = INVALID_POINTER_ID;
  159.             break;
  160.         }
  161.  
  162.         case MotionEvent.ACTION_CANCEL: {
  163.             mActivePointerId = INVALID_POINTER_ID;
  164.             break;
  165.         }
  166.  
  167.         case MotionEvent.ACTION_POINTER_UP: {
  168.             final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
  169.             final int pointerId = ev.getPointerId(pointerIndex);
  170.             if (pointerId == mActivePointerId) {
  171.                 // This was our active pointer going up. Choose a new
  172.                 // active pointer and adjust accordingly.
  173.                 final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
  174.                 mLastTouchX = ev.getX(newPointerIndex);
  175.                 mLastTouchY = ev.getY(newPointerIndex);
  176.                 mActivePointerId = ev.getPointerId(newPointerIndex);
  177.  
  178.             }
  179.             break;
  180.         }
  181.         }
  182.     }
  183.     return true;
  184. }
  185.  
  186. public void moveBitmap(float x, float y) {
  187.  
  188.     // Adjust for zoom factor. Otherwise, the user's finger moving 10 pixels
  189.     // at 200% zoom causes the image to slide 20 pixels instead of perfectly
  190.     // following the user's touch
  191.  
  192.     x = x / mScaleFactor;
  193.     y = y / mScaleFactor;
  194.  
  195.     bPosX = x;
  196.     bPosY = y;
  197.  
  198. }
  199.  
  200. public void moveCanvas(float x, float y) {
  201.     float dx = x - mLastTouchX;
  202.     float dy = y - mLastTouchY;
  203.  
  204.     // Adjust for zoom factor. Otherwise, the user's finger moving 10 pixels
  205.     // at 200% zoom causes the image to slide 20 pixels instead of perfectly
  206.     // following the user's touch
  207.     dx /= (mScaleFactor * 2);
  208.     dy /= (mScaleFactor * 2);
  209.  
  210.     mPosX += dx;
  211.     mPosY += dy;
  212.  
  213.     // Log.v(TAG, "moving by " + dx + "," + dy + " mScaleFactor: " +
  214.     // mScaleFactor);
  215. }
  216.  
  217. private class ScaleListener extends
  218.         ScaleGestureDetector.SimpleOnScaleGestureListener {
  219.     @Override
  220.     public boolean onScale(ScaleGestureDetector detector) {
  221.         mScaleFactor *= detector.getScaleFactor();
  222.         // Don't let the object get too small or too large.
  223.         mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
  224.         // Log.d(TAG, "detector scale factor: " + detector.getScaleFactor()
  225.         // + " mscalefactor: " + mScaleFactor);
  226.  
  227.         invalidate();
  228.         return true;
  229.     }
  230. }
Parsed in 0.061 seconds, using GeSHi 1.0.8.4
rensu
Freshman
Freshman
 
Posts: 2
Joined: Fri Apr 12, 2013 12:24 pm

Top

Return to Android 2D/3D Graphics - OpenGL Problems

Who is online

Users browsing this forum: No registered users and 4 guests