从缩放的画布获得准确的触摸位置(从屏幕坐标到画布坐标) [英] To get exact touch position (from screen coordinates to canvas coordinates) from a scaled canvas

查看:312
本文介绍了从缩放的画布获得准确的触摸位置(从屏幕坐标到画布坐标)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,



我有一个应用程序可以在屏幕边界内缩放/平移图像。
我在如下定义的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
:layout_height =match_parent
>

< com.example.panzoomapplication.panzoom.CustomImageView
android:id =@ + id / drawing_view
android:layout_width =wrap_content
: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();
//不要让对象变得太小或太大。
mScaleFactor = Math.max(MIN_ZOOM,Math.min(mScaleFactor,MAX_ZOOM));
calculatePanZoomMatrix();
return true;
}
}

private void calculatePanZoomMatrix(){
mPanZoomMatrix.reset();
//将视图w.r.t缩放到画布的中心。
mPanZoomMatrix.setScale(mScaleFactor,mScaleFactor,getWidth()/ 2,getHeight()/ 2);
invalidate()
}

和onDraw()的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)

 <$ c $ 

c> 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;
}

但最终会出现同样的问题。



您能帮我解决这个问题吗?我已经google了很多,但没有完美的解决方案。

解决方案

你不应该使用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();


Hi,

I have an application which zoom/pans the image within screen bounds. I have custom ImageView class inside my CustomFrameLayout as defined below.

<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>

I am scaling canvas in CustomFrameLayout class using,

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);
                     }

The canvas zooms well and takes correct touch position when mScalFactor = 1 (or in initial state). But when scaled by a factor greater than 1, the touch event coordinate shifts by a certain amount. I have tried to simulate this issue by drawing a circle at touch position in CustomImageView class.

                @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);
                       }

The circle draws well at initial state of canvas (mScalFactor = 1), but shifts its position from actual touch point when scaled by a factor greater than 1. I have tried to fix this issue using matrix as follows,

            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;
              }

but end up with same problem.

Could you please help me to fix this issue? I have googled a lot but with no perfect solution.*

解决方案

You shouldn't use Canvas to scale, is better to use matrix

to get touch coordinates from image(not screen):

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);

}

to get coordinates of screen use:

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

这篇关于从缩放的画布获得准确的触摸位置(从屏幕坐标到画布坐标)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆