• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Finding and moving Bitmaps after canvas scale

rensu

Lurker
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

[HIGH]public void onDraw(Canvas canvas) {
// Log.v(TAG, "onDraw()");
clipBounds = canvas.getClipBounds();
if (bitmap == null) {
Log.w(TAG, "nothing to draw - bitmap is null");
super.onDraw(canvas);
return;
}

if (firstDraw && (bitmap.getHeight() > 0) && (bitmap.getWidth() > 0)) {
// Don't let the user zoom out so much that the image is smaller
// than its containing frame
float minXScaleFactor = (float) viewWidth
/ (float) bitmap.getWidth();
float minYScaleFactor = (float) viewHeight
/ (float) bitmap.getHeight();
minScaleFactor = Math.max(minXScaleFactor, minYScaleFactor);
Log.d(TAG, "minScaleFactor: " + minScaleFactor);
// mScaleFactor = minScaleFactor; //start out "zoomed out" all the
// way

mPosX = mPosY = 0;
firstDraw = false;
}
mScaleFactor = Math.max(mScaleFactor, minScaleFactor);

canvasHeight = canvas.getHeight();
canvasWidth = canvas.getWidth();
// Log.d(TAG, "canvas density: " + canvas.getDensity() +
// " bitmap density: " + bitmap.getDensity());

// Log.d(TAG, "mScaleFactor: " + mScaleFactor);

// Save the canvas without translating (panning) or scaling (zooming)
// After each change, restore to this state, instead of compounding
// changes upon changes
canvas.save();
int maxX, minX, maxY, minY;
// Regardless of the screen density (HDPI, MDPI) or the scale factor,
// The image always consists of bitmap width divided by 2 pixels. If an
// image
// is 200 pixels wide and you scroll right 100 pixels, you just scrolled
// the image
// off the screen to the left.
minX = (int) (((viewWidth / mScaleFactor) - bitmap.getWidth()) / 2);
maxX = 0;
// How far can we move the image vertically without having a gap between
// image and frame?
minY = (int) (((viewHeight / mScaleFactor) - bitmap.getHeight()) / 2);
maxY = 0;
// Log.d(TAG, "minX: " + minX + " maxX: " + maxX + " minY: " + minY
// + " maxY: " + maxY);
// Do not go beyond the boundaries of the image
if (mPosX > maxX) {
mPosX = maxX;
}
if (mPosX < minX) {
mPosX = minX;
}
if (mPosY > maxY) {
mPosY = maxY;
}
if (mPosY < minY) {
mPosY = minY;
}

canvas.scale(mScaleFactor, mScaleFactor);
// canvas.scale(0.6f, 0.6f);
// Log.i("","mPos " + mPosX);
canvas.translate(mPosX, mPosY);

canvas.drawBitmap(bitmap, mPosX, mPosY, null);
canvas.drawBitmap(bmp, bPosX + mPosX, bPosY + mPosY, null);

if (!firstDraw) {
bitmapCanvas.drawBitmap(bitmap, mPosX, mPosY, null);
bitmapCanvas.drawBitmap(bmp, bPosX + mPosX, bPosY + mPosY, null);
}

super.onDraw(canvas);

canvas.restore(); // clear translation/scaling
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
if (zoomEnabled) {
mScaleDetector.onTouchEvent(ev);
}

if (panEnabled) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {

case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();

mLastTouchX = x;
mLastTouchY = y;

mActivePointerId = ev.getPointerId(0);

int mx = (int) mPosX * -1;
int my = (int) mPosY * -1;

// int checkPointX = (int) (x + mx * 2);
// int checkPointY = (int) (y + my * 2);

int checkPointX = (int) (x + mx * 2);
int checkPointY = (int) (y + my * 2);

Log.i("ZOOMS", "ScaleFactor " + mScaleFactor);
Log.i("TOUCH COORD", "x " + checkPointX + " y " + checkPointY);
Log.i("BMP POS", "x " + bPosX + " bw " + (bPosX + bmp.getWidth()) + " y " + bPosY + " yw " + (bPosY + bmp.getHeight()));

if (checkPointX > bPosX
&& checkPointX <= bPosX + bmp.getWidth()
&& checkPointY >= bPosY
&& checkPointY <= bPosY + bmp.getHeight())
bitmapFound = true;
else
bitmapFound = false;

// if(mx > bmp.)
break;
}

case MotionEvent.ACTION_MOVE: {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);

// Only move if the ScaleGestureDetector isn't processing a
// gesture.
if (!mScaleDetector.isInProgress()) {
if (bitmapFound) {
int mx = (int) mPosX * -1;
int my = (int) mPosY * -1;

int checkPointX = (int) (x + mx * 2);
int checkPointY = (int) (y + my * 2);

moveBitmap(checkPointX, checkPointY);
} else
moveCanvas(x, y);

invalidate();
}
mLastTouchX = x;
mLastTouchY = y;

break;
}

case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}

case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}

case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);

}
break;
}
}
}
return true;
}

public void moveBitmap(float x, float y) {

// Adjust for zoom factor. Otherwise, the user's finger moving 10 pixels
// at 200% zoom causes the image to slide 20 pixels instead of perfectly
// following the user's touch

x = x / mScaleFactor;
y = y / mScaleFactor;

bPosX = x;
bPosY = y;

}

public void moveCanvas(float x, float y) {
float dx = x - mLastTouchX;
float dy = y - mLastTouchY;

// Adjust for zoom factor. Otherwise, the user's finger moving 10 pixels
// at 200% zoom causes the image to slide 20 pixels instead of perfectly
// following the user's touch
dx /= (mScaleFactor * 2);
dy /= (mScaleFactor * 2);

mPosX += dx;
mPosY += dy;

// Log.v(TAG, "moving by " + dx + "," + dy + " mScaleFactor: " +
// mScaleFactor);
}

private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
// Log.d(TAG, "detector scale factor: " + detector.getScaleFactor()
// + " mscalefactor: " + mScaleFactor);

invalidate();
return true;
}
}[/HIGH]
 
Back
Top Bottom