围绕屏幕中心旋转画布,也允许翻译

时间:2017-04-15 23:17:39

标签: android graphics rotation

我使用canvas.drawPath绘制一个复杂的形状。这些drawPath方法的结果类似于比屏幕大的地图。我希望用户执行以下操作:使用一根手指移动地图。或者用两根手指围绕屏幕中心旋转。基本上它应该只与谷歌地图完全一样,没有缩放。到目前为止,我能够获得所需的移动和旋转:

private void handleTouch(MotionEvent event)
{
    switch(event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_POINTER_DOWN:
        {
            rotate=true;
            move=false;
            a=Math.toDegrees(-Math.atan2(event.getX(0)-event.getX(1),event.getY(0)-event.getY(1)));
            if(a>360)a=a-360;
            if(a<-360)a=a+360;
            da=a-angle;
            if(da>360)da=da-360;
            if(da<-360)da=da+360;

        }
        break;
        case MotionEvent.ACTION_POINTER_UP:
        {
            rotate=false;
            move=false;
            x = (int)event.getX();
            y = (int)event.getY();
            dx = x - translate.x;
            dy = y - translate.y;
        }
        break;
        case MotionEvent.ACTION_DOWN:
        {
            move=true;
            x = (int)event.getX();
            y = (int)event.getY();
            dx = x - translate.x;
            dy = y - translate.y;
        }
        break;
        case MotionEvent.ACTION_MOVE:
        {
            if(rotate && event.getPointerCount()==2)
            {
                angle=Math.toDegrees((-Math.atan2(event.getX(0)-event.getX(1),event.getY(0)-event.getY(1))))-da;
                if(angle>360)angle=angle-360;
                if(angle<-360)angle=angle+360;
                vmap.invalidate();

            }
            else if(move==true)
            {
                translate.set((int)event.getX() - dx,(int)event.getY() - dy);
                //trans.setTranslate(translate.x,translate.y);

                vmap.invalidate();

            }

        }
        break;
        case MotionEvent.ACTION_UP:
        {
            //your stuff
        }
        break;

    }

问题是将它们正确地应用在一起。如果我先翻译然后围绕地图的中心坐标旋转,我可以轻松地围绕自己的中心旋转。但是,如果我尝试围绕屏幕中心旋转,事情就会变得复杂起来。假设我将画布向左移动了20个像素,然后将其旋转了30度,然后向下移动了50个像素,然后将其旋转了50度。如果我尝试在第二次旋转期间将两个角度加在一起,我现在将围绕一个不同的坐标旋转,这意味着只要我进行新的旋转,地图就会突然跳跃。

我研究过使用矩阵,但到目前为止还没有帮助。

1 个答案:

答案 0 :(得分:0)

看一下Matrix课程。它允许您以多种方式转换ImageView。对于这个问题,我创建了一个包含成员的测试项目:

ImageView imageView;
Matrix imageMatrix = new Matrix();
PointF screenCenter = new PointF();

然后,在onCreate()中:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    screenCenter.x = metrics.widthPixels/2;
    screenCenter.y = metrics.heightPixels/2;

    imageView = (ImageView) findViewById(R.id.image);
    imageView.setScaleType(ImageView.ScaleType.MATRIX);
    imageMatrix.set(imageView.getImageMatrix());
}

screenCenter对象现在包含屏幕中心的坐标,稍后将使用。 imageView比例类型已设置为MATRIX,并且imageMatrix已设置为我们更改比例类型时应用于视图的起始矩阵。

现在,当您翻译时修改imageMatrix,然后使用setImageMatrix()将新矩阵应用于视图:

void translate(float x, float y) {
    imageMatrix.postTranslate(x, y);
    imageView.setImageMatrix(imageMatrix);
}

旋转的工作方式相同,但我们需要屏幕中心的坐标:

void rotate(float angle) {
    imageMatrix.postRotate(angle, screenCenter.x, screenCenter.y);
    imageView.setImageMatrix(imageMatrix);
}

这适用于我的模拟器,平移移动预期的方向,旋转始终围绕屏幕中心移动,无论它如何翻译。不可否认,这是一个测试项目,它看起来不太漂亮。

OpenGL ES包含在Android框架中,如果你走这条路线,你可能会获得更好的图形性能。如果您这样做,那么this answer可能会有帮助。