Android 如何在放大时找到单击的绝对位置

Android 如何在放大时找到单击的绝对位置,android,math,zooming,Android,Math,Zooming,请参阅下面的每一部分,了解我的问题的三种不同描述。希望能帮助人们回答这个问题 问题:在给定原始比例点和比例因子的情况下,仅以缩放图像的形式表示坐标时,如何找到以画布/用户空间表示的一对坐标 实践中的问题: 我目前正在尝试复制gallery/maps等应用程序中使用的缩放功能,当缩放移动到收缩的中点时,您可以通过收缩进行缩放/缩小 向下时,我保存缩放的中心点(基于当前屏幕的X、Y坐标)。然后,当检测到“缩放”手势时,我让此功能动作: class ImageScaleGestureDetector

请参阅下面的每一部分,了解我的问题的三种不同描述。希望能帮助人们回答这个问题

问题:在给定原始比例点和比例因子的情况下,仅以缩放图像的形式表示坐标时,如何找到以画布/用户空间表示的一对坐标

实践中的问题:

我目前正在尝试复制gallery/maps等应用程序中使用的缩放功能,当缩放移动到收缩的中点时,您可以通过收缩进行缩放/缩小

向下时,我保存缩放的中心点(基于当前屏幕的X、Y坐标)。然后,当检测到“缩放”手势时,我让此功能动作:

class ImageScaleGestureDetector extends SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        if(mScaleAllowed) 
            mCustomImageView.scale(detector.getScaleFactor(), mCenterX, mCenterY);
        return true;
    }
}   
CustomImageView的缩放功能如下所示:

public boolean scale(float scaleFactor, float focusX, float focusY) {
    mScaleFactor *= scaleFactor;

    // Don't let the object get too small or too large.
    mScaleFactor = Math.max(MINIMUM_SCALE_VALUE, Math.min(mScaleFactor, 5.0f));

    mCenterScaleX = focusX;
    mCenterScaleY = focusY;

    invalidate();

    return true;
}
缩放图像的绘制是通过覆盖onDraw方法实现的,onDraw方法围绕中心缩放画布,并将图像绘制到画布上

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    canvas.save();
    canvas.translate(mCenterScaleX, mCenterScaleY);
    canvas.scale(mScaleFactor, mScaleFactor);
    canvas.translate(-mCenterScaleX, -mCenterScaleY);
    mIcon.draw(canvas);
    canvas.restore();
}
当从ScaleFactor 1缩放时,这一切都可以正常工作,这是因为初始的mCenterX和mCenterY是基于设备屏幕的坐标。设备上的10,10是画布上的10,10

但是,在已经缩放之后,下次单击位置10,10时,它将不再对应于画布中的10,10,因为已经执行了缩放和变换

抽象问题:

下图是围绕中心点a进行缩放操作的示例。每个框表示处于该比例因子(1、2、3、4、5)时视图的位置和大小

在本例中,如果围绕a按因子2缩放,然后单击位置B,则报告为B的X,Y将基于屏幕位置,而不是相对于初始画布的0,0的位置


我需要找到一种获得B绝对位置的方法。

真的很抱歉,这是一个简短的回答,很匆忙。但我最近也一直在看这篇文章——我发现可以做你想做的事(我想——我不得不浏览一下你的文章)。希望这有帮助。如果这不起作用,我今晚会好好看看,看看我是否能进一步提供帮助。

因此,在重新绘制问题后,我找到了我一直在寻找的解决方案。它经过了几次迭代,但我是这样计算出来的:

B点,秤操作的中心

A1、A2、A3-点,在用户空间中相等,但在画布空间中不同

您知道
Bx
By
的值,因为无论比例因子是什么,它们总是恒定的(您在画布空间和用户空间中都知道该值)

您知道用户空间中的
Ax
Ay
,因此您可以通过
找到
Ax
Bx
Ay
之间的距离。此度量值在用户空间中,要将其转换为画布空间度量值,只需将其除以比例因子即可。(转换为画布空间后,您可以看到这些红色、橙色和黄色线条)

由于点
B
是恒定的,因此它与边之间的距离是恒定的(用蓝线表示)。此值在用户空间和画布空间中相等

您知道画布空间中画布的宽度,因此,从画布空间中点A的总宽度减去这两个画布空间测量值(
Ax
Bx
Bx
Edge
):

public float[] getAbsolutePosition(float Ax, float Ay) {
    
    float fromAxToBxInCanvasSpace = (mCenterScaleX - Ax) / mScaleFactor;
    float fromBxToCanvasEdge = mCanvasWidth - Bx;
    float x = mCanvasWidth - fromAxToBxInCanvasSpace - fromBxToCanvasEdge;
    
    float fromAyToByInCanvasSpace = (mCenterScaleY - Ay) / mScaleFactor;
    float fromByToCanvasEdge = mCanvasHeight - By;
    float y = mCanvasHeight - fromAyToByInCanvasSpace - fromByToCanvasEdge;
    
    return new float[] { x, y };
}
上面的代码和图像描述了您单击原始中心左上角时的情况。我使用相同的逻辑找到了一个无所谓的象限,并将其重构为以下内容:

public float[] getAbsolutePosition(float Ax, float Ay) {

    float x = getAbsolutePosition(mBx, Ax);
    float y = getAbsolutePosition(mBy, Ay); 

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

private float getAbsolutePosition(float oldCenter, float newCenter, float mScaleFactor) {
    if(newCenter > oldCenter) {
        return oldCenter + ((newCenter - oldCenter) / mScaleFactor);
    } else {
        return oldCenter - ((oldCenter - newCenter) / mScaleFactor);
    }
}

以下是我根据Graeme的答案提出的解决方案:

public float[] getAbsolutePosition(float Ax, float Ay) {
    MatrixContext.drawMatrix.getValues(mMatrixValues);

    float x = mWidth - ((mMatrixValues[Matrix.MTRANS_X] - Ax) / mMatrixValues[Matrix.MSCALE_X])
            - (mWidth - getTranslationX());

    float y = mHeight - ((mMatrixValues[Matrix.MTRANS_Y] - Ay) / mMatrixValues[Matrix.MSCALE_X])
            - (mHeight - getTranslationY());

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

参数Ax和Ay是用户通过onTouch()触摸的点,我在MatrixContext类中拥有我的静态矩阵实例来保存以前的缩放/转换值。

Android+的标准视图缩放设置轴点无法完成此任务?不确定“标准视图缩放和轴点设置”是什么意思?如果你能扩展一下,那就太好了。我的意思是用
setScaleX()
setScaleY(()
进行缩放,用
setPivotX()
setPivotY()
设置缩放中心。它们都是视图的方法,但我刚刚读到这些方法的Minsdk版本是11(蜂巢),因此,如果您针对早期版本,这些信息可能对您毫无用处。不幸的是,在2.3上:(谢谢您的建议!希望将来会对某人有所帮助!Sony Ericson在缩放方面有一个图坦卡门,这可能会有所帮助。我不得不原谅,因为我在这一点上很累,但在这个家伙的源代码中,他使用了“MultiTouchObjectCanvas”。在此界面中,有一个名为“getPositionAndScale”的方法,描述为“获取被拖动对象原点的屏幕坐标,并使用缩放倍增器将屏幕坐标转换为对象坐标”。"这正是我想要的-不幸的是,我看不到这个接口是在哪里实现的…看看他的演示-嘿,格雷姆,我面临着类似的问题?这让我从上个月开始头疼。最后我发现了一个问题,这个问题与我面临的问题相同。我需要你的帮助来破解这个解决方案?我理解你的想法上面的逻辑有点小,但需要你更多的帮助…我应该在哪里与你联系?提前谢谢我是
Android
聊天室的所有者之一-我会在那里。但在聊天室中,只有所有者指定的用户才能聊天?请接受请求。谢谢,请查看此信息,因为我无法进入聊天室。我发布了此问题嗨@格雷姆,你能解释一下最后一段代码的用途吗?例如,在第一个方法中,你不在这里调用相同的方法:“float x=getAbsolutePosition(mBx,Ax);”?我也没有得到与