从缩放的画布获得精确的触摸位置(从屏幕坐标到画布坐标)

时间:2014-04-15 10:13:00

标签: android canvas touch scale

您好,

我有一个应用程序可以在屏幕范围内缩放/平移图像。 我在CustomFrameLayout中定制了ImageView类,如下所示。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:background="@android:color/darker_gray" >

<com.example.panzoomapplication.panzoom.CustomFrameLayout
                        android:id="@+id/custom_frame_layout"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        >

<com.example.panzoomapplication.panzoom.CustomImageView
                            android:id="@+id/drawing_view"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:drawingCacheQuality="high"
                            android:layout_gravity="center"
                            android:src="@drawable/image"
                            android:adjustViewBounds="true" />
</com.example.panzoomapplication.panzoom.CustomFrameLayout>

</FrameLayout>

我正在使用

在CustomFrameLayout类中缩放画布
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

                    @Override
                    public boolean onScale(ScaleGestureDetector detector) {
                        mScaleFactor *= detector.getScaleFactor();
                        // Don't let the object get too small or too large.
                        mScaleFactor = Math.max(MIN_ZOOM, Math.min(mScaleFactor, MAX_ZOOM));
                        calculatePanZoomMatrix();
                        return true;
                    }
                }

                    private void calculatePanZoomMatrix() {
                     mPanZoomMatrix.reset();
                     // scale the view w.r.t to center of the canvas.
                     mPanZoomMatrix.setScale(mScaleFactor, mScaleFactor, getWidth() / 2, getHeight() / 2);
                     invalidate();
                    }

                    and in ondraw() of CustomFrameLayout,

                     @Override
                     protected void onDraw(Canvas canvas) {
                         canvas.concat(mPanZoomMatrix);
                     }

当mScalFactor = 1(或处于初始状态)时,画布变焦并获得正确的触摸位置。但是当按大于1的因子缩放时,触摸事件坐标移动一定量。我试图通过在CustomImageView类中的触摸位置绘制一个圆来模拟这个问题。

                @Override
                    protected void onDraw(Canvas canvas) {
                        super.onDraw(canvas);
                        Paint paint = new Paint();
                        paint.setPathEffect(null);
                        paint.setStyle(Paint.Style.FILL_AND_STROKE);
                        paint.setColor(getResources().getColor(R.color.red));
                        if (mCirclePoint != null)
                            canvas.drawCircle(touchEvent.x, touchEvent.y, 6, paint);
                       }

圆圈在画布的初始状态下绘制得很好(mScalFactor = 1),但是在缩放大于1的因子时将其位置从实际触摸点移开。我试图使用矩阵修复此问题,如下所示,

            public float[] getAbsolutePosition(float touchX, float touchY) {
                    float[] scaledPoints = new float[2];
                    scaledPoints[0] = touchX ;
                    scaledPoints[1] = touchY;
                    Matrix matrix = new Matrix();
                    matrix.reset();
                    foat scaleFactor = mCustomFrameLayout.getScaleFactor();
                    float centerX = mCustomFrameLayout.getCenterScaleX();
                    float centerY = mCustomFrameLayout.getCenterScaleY();
                    matrix.setScale(scaleFactor, scaleFactor, centerX, centerY);
                    matrix.mapPoints(scaledPoints);
                   return scaledPoints;
              }

但最终遇到同样的问题。

你能帮我解决这个问题吗?我搜索了很多但没有完美的解决方案。*

1 个答案:

答案 0 :(得分:1)

你不应该使用Canvas进行缩放,最好使用矩阵

从图像(非屏幕)获取触摸坐标:

void coorImagen(MotionEvent e){
    float []m = new float[9];
    matrix.getValues(m);
    float transX = m[Matrix.MTRANS_X] * -1;
    float transY = m[Matrix.MTRANS_Y] * -1;
    float scaleX = m[Matrix.MSCALE_X];
    float scaleY = m[Matrix.MSCALE_Y];
    lastTouchX = (int) ((e.getX() + transX) / scaleX);
    lastTouchY = (int) ((e.getY() + transY) / scaleY);
    lastTouchX = Math.abs(lastTouchX);
    lastTouchY = Math.abs(lastTouchY);

}

获取屏幕使用的坐标:

e.getX();
e.getY();