Android旋转拨号器ontouch

时间:2013-02-21 21:10:52

标签: android image bitmap android-animation

我正在阅读有关旋转图像的教程(在我的例子中是一个轮子)

我需要角度,但每当我再次触摸滚轮时,它从0开始,但它必须从最后一个角度开始。

任何人都可以解释&告诉我该怎么做?

这是我的代码:

public class MainActivity extends Activity {

private static Bitmap imageOriginal, imageScaled;
private static Matrix matrix;
private ImageView dialer;
private int dialerHeight, dialerWidth;
private GestureDetector detector;
private boolean[] quadrantTouched;
private boolean allowRotating;
private double startAngle, currentAngle, current_Angle;
MotionEvent e;
boolean isClicked = false;
private SensorManager mSensorManager;
private ShakeEventListener mSensorListener;


@Override
public void onCreate(Bundle b) {
    super.onCreate(b);
    setContentView(R.layout.activity_soundboard);   
    this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

    /*
     * Dit regelt het roteren van het wiel.
     */
    if (imageOriginal == null) {
        imageOriginal = BitmapFactory.decodeResource(getResources(), R.drawable.wheelcircle);
    }
    // initialize the matrix only once
    if (matrix == null) {
        matrix = new Matrix();
    } else {
        // not needed, you can also post the matrix immediately to restore the old state
        matrix.reset();
    }
    detector = new GestureDetector(this, new MyGestureDetector());
    quadrantTouched = new boolean[] { false, false, false, false, false };
    allowRotating = true;
    dialer = (ImageView) findViewById(R.id.imageView);
    dialer.setOnTouchListener(new MyOnTouchListener());
    dialer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // method called more than once, but the values only need to be initialized one time
            if (dialerHeight == 0 || dialerWidth == 0) {
                dialerHeight = dialer.getHeight();
                dialerWidth = dialer.getWidth();
                // resize
                Matrix resize = new Matrix();
                resize.postScale((float)Math.min(dialerWidth, dialerHeight) /    (float)imageOriginal.getWidth(), (float)Math.min(dialerWidth, dialerHeight) / (float)imageOriginal.getHeight());
                imageScaled = Bitmap.createBitmap(imageOriginal, 0, 0, imageOriginal.getWidth(), imageOriginal.getHeight(), resize, false);
                // translate to the image view's center
                float translateX = dialerWidth / 2 - imageScaled.getWidth() / 2;
                float translateY = dialerHeight / 2 - imageScaled.getHeight() / 2;
                matrix.postTranslate(translateX, translateY);
                dialer.setImageBitmap(imageScaled);
                dialer.setImageMatrix(matrix);
            }
        }
    }); 
}



private class MyOnTouchListener implements View.OnTouchListener {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                for (int i = 0; i < quadrantTouched.length; i++) {
                    quadrantTouched[i] = false;
                }
                allowRotating = false;
                startAngle = getAngle(event.getX(), event.getY());
                break;
            case MotionEvent.ACTION_MOVE:
                currentAngle = getAngle(event.getX(), event.getY());
                rotateDialer((float) (startAngle - currentAngle));
                startAngle = currentAngle;
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        quadrantTouched[getQuadrant(event.getX() - (dialerWidth / 2), dialerHeight - event.getY() - (dialerHeight / 2))] = true;
        detector.onTouchEvent(event);
        Log.e("Angle", currentAngle + "");
        return true;
    }
}

private class MyGestureDetector extends SimpleOnGestureListener {
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        // get the quadrant of the start and the end of the fling
        int q1 = getQuadrant(e1.getX() - (dialerWidth / 2), dialerHeight - e1.getY() - (dialerHeight / 2));
        int q2 = getQuadrant(e2.getX() - (dialerWidth / 2), dialerHeight - e2.getY() - (dialerHeight / 2));
        // the inversed rotations
        if ((q1 == 2 && q2 == 2 && Math.abs(velocityX) < Math.abs(velocityY))
                || (q1 == 3 && q2 == 3)
                || (q1 == 1 && q2 == 3)
                || (q1 == 4 && q2 == 4 && Math.abs(velocityX) > Math.abs(velocityY))
                || ((q1 == 2 && q2 == 3) || (q1 == 3 && q2 == 2))
                || ((q1 == 3 && q2 == 4) || (q1 == 4 && q2 == 3))
                || (q1 == 2 && q2 == 4 && quadrantTouched[3])
                || (q1 == 4 && q2 == 2 && quadrantTouched[3])) {
            dialer.post(new FlingRunnable(-1 * (velocityX + velocityY)));
        } else {
            // the normal rotation
            dialer.post(new FlingRunnable(velocityX + velocityY));
        }
        return true;
    }
}

private class FlingRunnable implements Runnable {
    private float velocity;
    public FlingRunnable(float velocity) {
        this.velocity = velocity;
    }
    @Override
    public void run() {
        if (Math.abs(velocity) > 5 && allowRotating) {
            rotateDialer(velocity / 75);
            velocity /= 1.0666F;
            // post this instance again
            dialer.post(this);
        }
    }
}

private double getAngle(double xTouch, double yTouch) {
    double x = xTouch - (dialerWidth / 2d);
    double y = dialerHeight - yTouch - (dialerHeight / 2d);
    switch (getQuadrant(x, y)) {
        case 1:
            return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
        case 2:
            return 180 - Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
        case 3:
            return 180 + (-1 * Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
        case 4:
            return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
        default:
            return 0;
    }
}
/**
 * @return The selected quadrant.
 */
private static int getQuadrant(double x, double y) {
    if (x >= 0) {
        return y >= 0 ? 1 : 4;
    } else {
        return y >= 0 ? 2 : 3;
    }
}



private void rotateDialer(float degrees) {
    matrix.postRotate(degrees, dialerWidth / 2, dialerHeight / 2);
    dialer.setImageMatrix(matrix);
}

}

1 个答案:

答案 0 :(得分:0)

也许使用保存以前角度的全局变量?

case MotionEvent.ACTION_DOWN:
                for (int i = 0; i < quadrantTouched.length; i++) {
                    quadrantTouched[i] = false;
                }
                allowRotating = false;
                startAngle = previousAngle;
                break;
            case MotionEvent.ACTION_MOVE:
                currentAngle = getAngle(event.getX(), event.getY());
                rotateDialer((float) (startAngle - currentAngle));                    
                startAngle = currentAngle;
                break;
            case MotionEvent.ACTION_UP:
                previousAngle = currentAngle;
                break;

这可能不会像这样工作,但你明白了......