3

这是我关于stackoverflow的第一个问题,所以请放轻松。

让我给你一点背景:

我创建了一个在视图中操作位图的应用程序(在这种情况下,图像是设施的地图),我使用位图上点的实际 x 和 y 坐标在地图上放置点。我跟踪位图左上角相对于屏幕左上角的偏移,方法是根据手势对图像位置的更改修改此偏移值。这实际上非常适合平移,这使我可以轻松地将屏幕坐标(从长按手势)转换为位图上的实际坐标。有了这个,我在地图上画了一个圆圈,并允许用户创建一个我推送到数据库的“兴趣点”。

处理缩放时会出现问题。我
canvas.scale(scalefastor ,scalefactor); 在 onDraw 中用一个简单的缩放。使用此缩放,实际缩放是相对于图像的左上角的,因此缩放缩放并不直观,因为您尝试放大的实际位置非常快地跑出屏幕。但是,以这种方式缩放图像不会影响图像的实际偏移量,因此我的点放置仍然准确。我使用以下简单的数学来完成此操作:

bitmapXCoordinate = (event.getX() - xOffset) /scaleFactor;

我想用

canvas.scale(scalefactor, scalefactor, gestureFocusX, gestureFocusY);

为了保持缩放对用户直观,但这会对位图的实际矩阵进行转换,因此我的点放置不再起作用。似乎位图上的点现在以某种方式相对于比例的焦点,并且所有放置的点都关闭并趋向于该焦点。我知道我需要考虑矩阵上的这种转换才能正确放置我的点,但显然,它需要一个比我更聪明的人。解决方案可能很简单,但我已经为此工作了好几天试图解释这个新的偏移量,但我无法获得任何真正的进展。对此解决方案的任何见解将不胜感激。

4

1 回答 1

0

我为此苦苦挣扎了一个多星期,尝试了各种解决方案,然后才找到了一些虽然我不完全理解的东西;),但有工作的好处。您将需要一个捏缩放(或其他)图像视图的工作实现,您可以从中得出当前的比例和平移值。

我认为这个问题的困难在于有两个问题需要解决:1,解码可能缩放和翻译的图像上的点击,以及 2,渲染存储的点击位置。

无论如何,到代码。要注册触摸:

private Float[] getNormalizedTouchLocation(MotionEvent event) {
    float xpos = getOffsetX();
    float ypos = getOffsetY();
    float scale = getScaleFactor();

    Drawable drawable = getDrawable();
    Rect image_bounds = drawable.getBounds();

    Matrix matrix = new Matrix(getImageMatrix());

    matrix.postScale(scale, scale, mPivotX, mPivotY);
    matrix.postTranslate(xpos, ypos);

    RectF image_rect = new RectF(image_bounds);

    matrix.mapRect(image_rect);

    float x = ((event.getX() - image_rect.left) / scale);
    float y = ((event.getY() - image_rect.top) / scale);

    return new Float[]{x, y};
}

然后渲染:

public void onDraw(Canvas canvas) {
    // Ensure parent leaves the canvas *unscaled* and *untranslated*.
    super.onDraw(canvas);

    float xpos = getOffsetX();
    float ypos = getOffsetY();
    float scale = getScaleFactor();

    canvas.save();

    Matrix matrix = canvas.getMatrix();
    matrix.postScale(scale, scale, mPivotX, mPivotY);
    matrix.postTranslate(xpos, ypos);

    Drawable drawable = getDrawable();
    Rect image_bounds = drawable.getBounds();

    RectF image_rect = new RectF(image_bounds);

    Matrix image_matrix = new Matrix(getImageMatrix());
    image_matrix.postScale(scale, scale, mPivotX, mPivotY);
    image_matrix.postTranslate(xpos, ypos);

    image_matrix.mapRect(image_rect);

    // mPoints is a list of float[2] coordinates.
    for (Float[] coord: mPoints) {

        // Draw a bitmap centered on each touch position.
        float x = (scale * coord[0] + image_rect.left) - mBitmap.getWidth() / 2;
        float y = (scale * coord[1] + image_rect.top) - mBitmap.getHeight() / 2;

        canvas.drawBitmap(mBitmap, x, y, mPaint);
    }

    canvas.restore();
}

希望这对你有用!显然,这里的解决方案仅在相同的屏幕分辨率等下正确渲染在相同渲染大小的图像上注册的点 - 它可能会被修改为存储图像宽度/高度的分数,以用于跨图像/分辨率的解决方案。

于 2013-05-05T00:40:01.163 回答