触摸屏未根据缩放图像进行调整

时间:2015-12-11 06:03:49

标签: android

我在android中进行图像注释,并在其中添加了缩放功能。所以现在当我缩放图像并在那之后进行任何注释时,它不在我触摸屏幕的那一点上,而不是像原始图像那样(Unzoomed Image)。

onDraw方法

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    onDrawReady = true;             

    imageRenderedAtLeastOnce = true;
    canvas.concat(matrix);

    for (DrawObject d : paths) {
        if (d.getType() == MODE_DRAWING) {
            canvas.drawPath(d.getPair().first, d.getPair().second); 
        } else if (d.getType() == MODE_TEXT) {
            canvas.drawText(d.getText(), d.getX(), d.getY(), d.getPair().second);
        } else if (d.getType() == MODE_ARROW) {
            canvas.drawLine(d.getStartX(), d.getStartY(), d.getX(), d.getY(), d.getPair().second);
            fillArrow(canvas, d.getStartX(), d.getStartY(), d.getX(), d.getY(), d.getPair().second);
        } else if (d.getType() == MODE_CIRCLE) {
            RectF oval2 = new RectF(d.getStartX(), d.getStartY(), d.getX(), d.getY());
            canvas.drawOval(oval2, d.getPair().second);
        } else if (d.getType() == MODE_RECTANGLE) {
            canvas.drawRect(d.getStartX(), d.getStartY(), d.getX(), d.getY(), d.getPair().second);
        } else if (d.getType() == MODE_ERASE) {
            canvas.drawPath(d.getPair().first, d.getPair().second);
        }
    }
    canvas.save();
}

onTouch方法

@Override
public boolean onTouch(View v, MotionEvent event) {                 
        mScaleDetector.onTouchEvent(event);
        mGestureDetector.onTouchEvent(event);
        PointF curr = new PointF(event.getX(), event.getY());

        mX = event.getX() + mDistX;
        mY = event.getY() + mDistY;

        if (state == State.NONE || state == State.DRAG || state == State.FLING) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                drawFlag = false;
                mStartX = mX;
                mStartY = mY;

                if (mMode == MODE_ARROW) {
                    mPath = new Path();
                    mLineDrawObject = new DrawObject(MODE_ARROW, new Pair<Path, Paint>(mPath, getLinePaint()));
                    drawFlag = true;
                } else if (mMode == MODE_TEXT) {
                    drawFlag = true;
                } else if (mMode == MODE_CIRCLE) {
                    mPath = new Path();
                    mCircleDrawObject = new DrawObject(MODE_CIRCLE, new Pair<Path, Paint>(mPath, getCirclePaint()));
                    drawFlag = true;
                } else if (mMode == MODE_RECTANGLE) {
                    mPath = new Path();
                    mRectangleObject = new DrawObject(MODE_RECTANGLE, new Pair<Path, Paint>(mPath, getRectanglePaint()));
                    drawFlag = true;
                } else if (mMode == MODE_DRAWING) {
                    mPath = new Path();
                    mDrawingDrawObject = new DrawObject(MODE_DRAWING, new Pair<Path, Paint>(mPath, getDrawPaint()));
                    drawFlag = true;
                } else if (mMode == MODE_ERASE) {
                    mPath = new Path();
                    mEraseObject = new DrawObject(MODE_ERASE, new Pair<Path, Paint>(mPath, getErasePaint()));
                    drawFlag = true;
                }
                if (drawFlag == true) {
                    touch_start(mX, mY);
                    invalidate();
                }

                last.set(curr);
                if (fling != null) {
                    fling.cancelFling();
                }
                setState(State.DRAG);
                break;

            case MotionEvent.ACTION_MOVE:
                if (state == State.DRAG && drawFlag == false) {
                    float deltaX = curr.x - last.x;
                    float deltaY = curr.y - last.y;
                    float fixTransX = getFixDragTrans(deltaX, viewWidth,
                            getImageWidth());
                    float fixTransY = getFixDragTrans(deltaY, viewHeight,
                            getImageHeight());
                    matrix.postTranslate(fixTransX, fixTransY);

                    fixTrans();
                    last.set(curr.x, curr.y);
                }
                if (drawFlag == true) {
                    touch_move(mX, mY);
                    invalidate();
                }
                break;

            case MotionEvent.ACTION_UP:
                if (drawFlag == true) {
                    touch_up();
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                setState(State.NONE);
                break;

            }
        }

        setImageMatrix(matrix);
        //mCanvas.concat(matrix);

        //
        // User-defined OnTouchListener
        //
        if (userTouchListener != null) {
            userTouchListener.onTouch(v, event);
        }

        //
        // OnTouchImageViewListener is set: TouchImageView dragged by user.
        //
        if (touchImageViewListener != null) {
            touchImageViewListener.onMove();
        }

        //
        // indicate event was handled
        //
        return true;
    }
}

2 个答案:

答案 0 :(得分:0)

您可以尝试以下onDraw和onTouch方法。

<强>的onDraw

 @Override
protected void onDraw(Canvas canvas) {
    onDrawReady = true;
    imageRenderedAtLeastOnce = true;
    if (delayedZoomVariables != null) {
        setZoom(delayedZoomVariables.scale, delayedZoomVariables.focusX, delayedZoomVariables.focusY, delayedZoomVariables.scaleType);
        delayedZoomVariables = null;
    }
    super.onDraw(canvas);
}

<强> onTouch

@Override
    public boolean onTouch(View v, MotionEvent event) {
        mScaleDetector.onTouchEvent(event);
        mGestureDetector.onTouchEvent(event);
        PointF curr = new PointF(event.getX(), event.getY());

        if (state == State.NONE || state == State.DRAG || state == State.FLING) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    last.set(curr);
                    if (fling != null)
                        fling.cancelFling();
                    setState(State.DRAG);
                    break;

                case MotionEvent.ACTION_MOVE:
                    if (state == State.DRAG) {
                        float deltaX = curr.x - last.x;
                        float deltaY = curr.y - last.y;
                        float fixTransX = getFixDragTrans(deltaX, viewWidth, getImageWidth());
                        float fixTransY = getFixDragTrans(deltaY, viewHeight, getImageHeight());
                        matrix.postTranslate(fixTransX, fixTransY);
                        fixTrans();
                        last.set(curr.x, curr.y);
                    }
                    break;

                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_POINTER_UP:
                    setState(State.NONE);
                    break;
            }
        }

        setImageMatrix(matrix);

        //
        // User-defined OnTouchListener
        //
        if(userTouchListener != null) {
            userTouchListener.onTouch(v, event);
        }

        //
        // OnTouchImageViewListener is set: TouchImageView dragged by user.
        //
        if (touchImageViewListener != null) {
            touchImageViewListener.onMove();
        }

        //
        // indicate event was handled
        //
        return true;
    }
}

答案 1 :(得分:0)

我终于找到了我问的问题的答案。 这是因为触摸坐标和画布坐标之间的像素映射差异。

将此添加到onTouch方法解决了我的问题

PointF curr = new PointF();
//Add this line
curr = transformCoordTouchToBitmap(event.getX(), event.getY(), false);
mX = curr.x;
mY = curr.y;

在代码中定义此方法。

private PointF transformCoordTouchToBitmap(float x, float y, boolean clipToBitmap) {
    matrix.getValues(m);
    float origW = getDrawable().getIntrinsicWidth();
    float origH = getDrawable().getIntrinsicHeight();
    float transX = m[Matrix.MTRANS_X];
    float transY = m[Matrix.MTRANS_Y];
    float finalX = ((x - transX) * origW) / getImageWidth();
    float finalY = ((y - transY) * origH) / getImageHeight();

    if (clipToBitmap) {
        finalX = Math.min(Math.max(finalX, 0), origW);
        finalY = Math.min(Math.max(finalY, 0), origH);
    }

    return new PointF(finalX, finalY);
}