基于触摸屏幕,让Android画布上的位图沿着圆形路径移动和旋转?

4

1
我以前做过这个...让我看看能否找到代码。 - selbie
你可以使用任何路径来实现此功能,使用PathMeasure类即可。 - pskink
但是那样会旋转图像吗? - user3011902
1个回答

7

更新:完整示例已发布在GitHub,网址为https://github.com/jselbie/xkcdclock

每次触摸事件发生时,请获取触摸点的x、y坐标,并计算相对于位图中心的旋转角度。使用该值来确定要绘制的位图需要旋转多少。

首先,假设一个逻辑坐标系,其中您元素的中心点在x、y空间中的位置为(0,0)。

因此,任何相对于中心的触摸点之间的角度(以度为单位)可以计算如下:

double ComputeAngle(float x, float y)
{
    final double RADS_TO_DEGREES = 360 / (java.lang.Math.PI*2);
    double result = java.lang.Math.atan2(y,x) * RADS_TO_DEGREES;

    if (result < 0)
    {
        result = 360 + result;
    }

    return result;
}

注意-将负角度转换为正角度。因此,如果触摸点为(20,20),则上述函数将返回45度。
要使用此方法,您的 Activity 需要定义以下成员变量:
float _refX;   // x coordinate of last touch event
float _refY;   // y coordinate or last touch event
float _rotation;  // what angle should the source image be rotated at
float _centerX;         // the actual center coordinate of the canvas we are drawing on
float _centerY;         // the actual center coordinate of the canvas we are drawing on

现在让我们来看一下如何跟踪触摸坐标,以便我们始终拥有最新的“_rotation”变量。
因此,我们的Android“触摸处理程序”将类似于以下内容:
boolean onTouch(View v, MotionEvent event)
{
    int action = event.getAction();
    int actionmasked = event.getActionMasked();

    if (!_initialized)
    {
        // if we haven't computed _centerX and _centerY yet, just bail
        return false;
    }

    if (actionmasked == MotionEvent.ACTION_DOWN)
    {
        _refX = event.getX();
        _refY = event.getY();
        return true;
    }
    else if (actionmasked == MotionEvent.ACTION_MOVE)
    {

        // normalize our touch event's X and Y coordinates to be relative to the center coordinate
        float x = event.getX() - _centerX;
        float y =  _centerY - event.getY();

        if ((x != 0) && (y != 0))
        {
            double angleB = ComputeAngle(x, y);

            x = _refX - _centerX;
            y = _centerY - _refY;
            double angleA = ComputeAngle(x,y);

            _rotation += (float)(angleA - angleB);

            this.invalidate();  // tell the view to redraw itself
        }
    }    

本文中有一些细节没有说明,例如如何绘制实际的位图。你可能还希望处理ACTION_UP和ACTION_CANCEL事件,以将_rotation规范化为始终在0到360之间。但是主要的点是上述代码是计算Bitmap应该在View上绘制的_rotation的框架。类似以下内容:

void DrawBitmapInCenter(Bitmap bmp, float scale, float rotation, Canvas canvas)
{
    canvas.save();
    canvas.translate(canvas.getWidth()/2, canvas.getHeight()/2);
    canvas.scale(scale, scale);
    canvas.rotate(rotation);
    canvas.translate(-bmp.getWidth()/2, -bmp.getHeight()/2);
    canvas.drawBitmap(bmp, 0, 0, _paint);
    canvas.restore();
}

2
在实现代码时,我遇到了两个问题。图像移动得太快了,并且它没有定位到我触摸屏幕的方向。 - user3011902
1
@TastyLemons - 我已经在 https://github.com/jselbie/xkcdclock 上发布了完整的 Android 项目示例。希望这能有所帮助。 - selbie
1
@TastyLemons - 你似乎还想让位图旋转到与手指按下的角度相同的位置。通过在ACTION_DOWN事件上调用ComputeAngle并将其设置为活动旋转,然后使视图无效以便重新绘制,这应该很容易添加。我不能为你编写代码,但是经过一些努力,你可以将我给你的内容适应到自己的需求中。 - selbie
谢谢 @selbie,你救了我。这段代码运行得很好。 - biswajitGhosh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接