Java 安卓旋转轮对终点

Java 安卓旋转轮对终点,java,android,rotation,Java,Android,Rotation,当我尝试在安卓系统中旋转轮子时,遇到了一些问题。我在网上研究,找到了一些可行的解决方案。代码如下: @Override public void onCreate(Bundle savedInstanceState) { //Get the content resolver cResolver = getContentResolver(); //Get the current window window = getWindow(); // load the

当我尝试在安卓系统中旋转轮子时,遇到了一些问题。我在网上研究,找到了一些可行的解决方案。代码如下:

@Override
public void onCreate(Bundle savedInstanceState) {
  //Get the content resolver
    cResolver = getContentResolver();

    //Get the current window
    window = getWindow();

    // load the image only once
    if (imageOriginal == null) {
        imageOriginal = BitmapFactory.decodeResource(getResources(), R.drawable.wheel);
    }

    // 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());

    // there is no 0th quadrant, to keep it simple the first value gets ignored
    quadrantTouched = new boolean[] { false, false, false, false, false };

    allowRotating = true;

    dialer = (ImageView) findViewById(R.id.imageView_ring);
    txtWheel = (TextView) findViewById(R.id.txtWheel);
    dialer.setOnTouchListener(new MyOnTouchListener());
    dialer.getViewTreeObserver().addOnGlobalLayoutListener(new 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 void rotateDialer(float degrees) {
    matrix.postRotate(degrees, dialerWidth / 2, dialerHeight / 2);  
    dialer.setImageMatrix(matrix);
}

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:
        case 3:
            return 180 - (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:
            // ignore, does not happen
            return 0;
    }
}

private static int getQuadrant(double x, double y) {
    if (x >= 0) {
        return y >= 0 ? 1 : 4;
    } else {
        return y >= 0 ? 2 : 3;
    }
}

private class MyOnTouchListener implements OnTouchListener {

    private double startAngle;

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:

                // reset the touched quadrants
                for (int i = 0; i < quadrantTouched.length; i++) {
                    quadrantTouched[i] = false;
                }

                allowRotating = false;

                startAngle = getAngle(event.getX(), event.getY());

                break;

            case MotionEvent.ACTION_MOVE:
                double currentAngle = getAngle(event.getX(), event.getY());
                rotateDialer((float) (startAngle - currentAngle));
                startAngle = currentAngle;

                txtWheel.setText("" + Math.round(startAngle));
                break;

            case MotionEvent.ACTION_UP:
                allowRotating = true;
                break;
        }

        // set the touched quadrant to true
        quadrantTouched[getQuadrant(event.getX() - (dialerWidth / 2), dialerHeight - event.getY() - (dialerHeight / 2))] = true;

        detector.onTouchEvent(event);

        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);
        }
    }
}
@覆盖
创建时的公共void(Bundle savedInstanceState){
//获取内容解析器
cResolver=getContentResolver();
//获取当前窗口
window=getWindow();
//仅加载图像一次
如果(imageOriginal==null){
imageOriginal=BitmapFactory.decodeResource(getResources(),R.drawable.wheel);
}
//只初始化矩阵一次
if(矩阵==null){
矩阵=新矩阵();
}否则{
//不需要,您也可以立即发布矩阵以恢复旧状态
matrix.reset();
}
detector=新的GestureDetector(这个,新的MyGestureDetector());
//没有第0象限,为了保持简单,第一个值被忽略
quadrantTouched=新布尔[]{false,false,false,false};
allowRotating=true;
拨号器=(ImageView)findViewById(R.id.ImageView\u环);
txtweel=(TextView)findViewById(R.id.txtweel);
setOnTouchListener(新的MyOnTouchListener());
dialer.getViewTreeObserver().addOnGlobalLayoutListener(新OnGlobalLayoutListener()){
@凌驾
公共图书馆{
//方法多次调用,但值只需初始化一次
如果(拨号键宽度==0 | |拨号键宽度==0){
dialerHeight=dialer.getHeight();
dialerWidth=dialer.getWidth();
//调整大小
矩阵大小=新矩阵();
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);
//平移到图像视图的中心
float translateX=dialerWidth/2-imageScaled.getWidth()/2;
float translateY=dialerHeight/2-imageScaled.getHeight()/2;
矩阵。后翻译(translateX,translateY);
dialer.setImageBitmap(图像缩放);
拨号器。设置图像矩阵(矩阵);
}
}
});
}
专用空心旋转测试器(浮动度){
矩阵。后旋转(度,拨号宽度/2,拨号高度/2);
拨号器。设置图像矩阵(矩阵);
}
专用双getAngle(双X触摸、双Y触摸){
双x=x触摸-(拨号宽度/2d);
双y=拨号键-y触摸-(拨号键/2d);
开关(象限(x,y)){
案例1:
返回Math.asin(y/Math.hypot(x,y))*180/Math.PI;
案例2:
案例3:
返回180-(Math.asin(y/Math.hypot(x,y))*180/Math.PI);
案例4:
返回360+Math.asin(y/Math.hypot(x,y))*180/Math.PI;
违约:
//忽略,不会发生
返回0;
}
}
专用静态整型象限(双x,双y){
如果(x>=0){
返回y>=0?1:4;
}否则{
返回y>=0?2:3;
}
}
私有类MyOnTouchListener实现OnTouchListener{
私人双星缠结;
@凌驾
公共布尔onTouch(视图v,运动事件){
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:
//重置触摸象限
对于(int i=0;iMath.abs(velocityY))
||((q1==2&&q2==3)| |(q1==3&&q2==2))
||((q1==3&&q2==4)| |(q1==4&&q2==3))
||(q1==2和q2==4和象限[3])
||(q1==4和q2==2和象限[3])){
拨号柱(新FlingRunnable(-1*(velocityX+velocityY));
}否则{
//法向旋转
拨号柱(新FlingRunnable(velocityX+velocityY));
}
返回true;
}
}
私有类FlingRunTable实现了Runnable{
私人浮动速度;
公共FlingRunnable(浮动速度){
速度=速度;
}
@凌驾
公开募捐{
如果(数学abs(速度)>5&&allowRotating){
旋转测试器(速度/75