I try to turn the view pushed inward by touching it and moving my finger. I came up with several solutions, but none of them feel natural on the device.
Here is my first approach: depending on where the user touched the screen and in which direction the finger was moved, I change the rotational rotation, calculated more or less arbitrarily.
private void updateRotation(float x, float y, float oldX, float oldY) {
int width = getWidth();
int height = getHeight();
float centerX = width / 2;
float centerY = height / 2;
float xSpeed = rotationSpeed(x, oldX, width);
float ySpeed = rotationSpeed(y, oldY, height);
if ((y < centerY && x > oldX)
|| (y > centerY && x < oldX))
rotation += xSpeed;
else if ((y < centerY && x < oldX)
|| (y > centerY && x > oldX))
rotation -= xSpeed;
if ((x > centerX && y > oldY)
|| (x < centerX && y < oldY))
rotation += ySpeed;
else if ((x > centerX && y < oldY)
|| (x < centerX && y > oldY))
rotation -= ySpeed;
}
private static float rotationSpeed(float pos, float oldPos, float max) {
return (Math.abs(pos - oldPos) * 180) / max;
}
This approach had several annoying side effects: sometimes the stretchable rotated until the finger moved, and the rotation was usually not as fast as the user's finger.
Therefore, I threw away this code and started with my second approach. I use trigonometry to calculate the actual rotation, which will be equivalent to the movement of the finger:
private void updateRotation(float x, float y, float oldX, float oldY) {
float centerX = getWidth() / 2;
float centerY = getHeight() / 2;
float a = distance(centerX, centerY, x, y);
float b = distance(centerX, centerY, oldX, oldY);
float c = distance(x, y, oldX, oldY);
double r = Math.acos((Math.pow(a, 2) + Math.pow(b, 2) - Math.pow(c, 2))
/ (2 * a * b));
if ((oldY < centerY && x < oldX)
|| (oldY > centerY && x > oldX)
|| (oldX > centerX && y < oldY)
|| (oldX < centerX && y > oldY))
r *= -1;
rotation += (int) Math.toDegrees(r);
}
private float distance(float x1, float y1, float x2, float y2) {
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
}
, . - ? , , .
, , , . , ?
Edit:
Snailer. atan2, , :
private void updateRotation(float x, float y) {
double r = Math.atan2(x - getWidth() / 2, getHeight() / 2 - y);
rotation = (int) Math.toDegrees(r);
}