Rotate canvas along its center based on user touch - Android

I want to rotate the canvas circularly on its center axis based on user touch.

i want to rotate based on center but its rotating based on top left corner .

so i am able to see only 1/4 for rotation of image.

any idea..

Like a old phone dialer .

I have tried like as follows

onDraw(Canvas canvas){
canvas.save();
// do my rotation
canvas.rotate(rotation,0,0);
canvas.drawBitmap( ((BitmapDrawable)d).getBitmap(),0,0,p );
canvas.restore();
}

@Override
public boolean onTouchEvent(MotionEvent e) {
float x = e.getX();
float y = e.getY();
updateRotation(x,y);
mPreviousX = x;
mPreviousY = y;
invalidate();
}

private void updateRotation(float x, float y) {

double r = Math.atan2(x - centerX, centerY - y);
rotation = (int) Math.toDegrees(r);
}

• First parameter to atan2 must be y in all implementations I know. Besides that, tell us where you are stuck. What is the problem? – Maik Semder Aug 13 '11 at 9:56
• i want to rotate based on center but its rotating based on top left corner . this is the issue – Ganapathy C Aug 13 '11 at 10:40

2 Answers

The core problem in your code is probably that you pass in 0, 0 as the pivot point to rotate about in your rotate call.

For a more robust way of expressing your transformation, in linear algebra the way to rotate about an arbitrary point is to translate the world in such a way that the point is at the origin, rotate, and then translate back.

That is, translate(-px, -py) * rotate(theta) * translate(px, py), where p is the point.

You can find an example at installation of android sdk

android-sdks/add-ons/addon-google_apis-google_inc_-8/samples/MapDemo


But maybe you have to change a bit two method to get right orientation on touch event.

private class RotateView extends ViewGroup implements SensorListener {

/* ...  */

private Matrix invertedMatrix = new Matrix();
private float[] tempLocation = new float[2];

@Override
protected void dispatchDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.rotate(mHeading, getWidth() * 0.5f, getHeight() * 0.5f);
canvas.getMatrix().invert(invertedMatrix);
mCanvas.delegate = canvas;
super.dispatchDraw(mCanvas);
canvas.restore();
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
centeringAllowed = false;

float[] location = tempLocation;
location[0] = ev.getX();
location[1] = ev.getY();
invertedMatrix.mapPoints(location);
ev.setLocation(location[0], location[1]);
return super.dispatchTouchEvent(ev);
}
}


This class is part of MapDemo project