Android: Wie das drehen eines Elements, indem Sie Sie berühren?

Ich versuche zu drehen, ein drawable innerhalb einer Ansicht, indem Sie Sie berühren und bewegen die finger. Ich habe mehrere Lösungen, aber keiner von Ihnen fühlt sich natürlich auf das Gerät.

Hier mein Erster Ansatz: Je nachdem, wo der Benutzer berührt den Bildschirm und in welche Richtung sich der finger bewegt wurde, ich bin ändern der drawable-rotation, berechnet mehr oder weniger willkürlich.

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;
}

Dieser Ansatz hatte ein paar ärgerliche Nebenwirkungen: Manchmal ist die drawable würde sich drehen, während die finger war nicht zu bewegen, und die Drehung war in der Regel nicht so schnell wie die user ' s finger.

Daher warf ich diesen code entfernt und begann mit meinem zweiten Ansatz. Ich bin mit der Trigonometrie zu berechnen, die tatsächliche Drehung das wäre äquivalent zu dem-finger-Bewegung:

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);
}

Obwohl diese klingt wie die richtige Lösung für mich, es funktioniert nicht gut entweder. Finger-Bewegung wird manchmal ignoriert, könnte die Berechnung zu teuer? Außerdem, die rotation ist immer noch ein bisschen schneller als der eigentliche finger-Bewegung.

Ideal, wenn ich beginnen zu drehen das drawable, das berühren eines bestimmten Punktes, an diesem Punkt sollte unten bleiben mit dem finger auf alle Zeiten. Können Sie mir sagen, wie dies zu erreichen?

Edit:

Hier ist meine Annahme Snailer Vorschlag. Ich hatte zu wechseln, die Argumente für die atan2 Methode zum drehen in die richtige Richtung, jetzt funktioniert es Super:

private void updateRotation(float x, float y) {
    double r = Math.atan2(x - getWidth() / 2, getHeight() / 2 - y);
    rotation = (int) Math.toDegrees(r);
}
InformationsquelleAutor fhd | 2010-11-14
Schreibe einen Kommentar