使用矩阵缩放焦点周围的图像视图的正确方法

时间:2013-08-26 19:40:14

标签: android android-imageview pinchzoom image-zoom

首先我要说的是,我已经阅读了大量的缩放问题并重新计算了这里的坐标。但我似乎无法将它们应用到我的情况中。

我有一个可以缩放和滚动的自定义ImageView类。我遇到的问题来自于按此顺序执行以下操作:

  1. 放大点,并将该点作为焦点(这可行)
  2. 在放大的同时滚动
  3. 尝试在不同点上放大/缩小(不起作用
  4. 以下是自定义视图的示例。有两个圆圈:红色和绿色。红色是焦点应该的位置,绿色是焦点接近实际的位置。 enter image description here

    当我尝试放大以橙色圈出的区域时出现问题。在下图中,我试图放大橙色圆圈区域(不是很多,只是为了显示焦点的计算位置)。如下所示,红色圆圈正确计算新焦点,但由于某种原因,绿色圆圈实际上是放大/缩小的位置。

    enter image description here

    我使用以下代码将缩放的坐标映射到实际的imageview坐标

    public boolean onScale(ScaleGestureDetector detector) {
            //update the current scale
        scaleFactor *= detector.getScaleFactor();
        scaleFactor = Math.max(ZOOM_LEVEL_4, Math.min(scaleFactor, ZOOM_LEVEL_0));
    
        //applying the scaleFactor to the focal point as determined in onScaleBegin
        transformMatrix.setScale(scaleFactor, scaleFactor, 
                      newFocalPoints[0], newFocalPoints[1]);
    
        //apply the matrix to the child
        child.transform(transformMatrix, newFocalPoints[0],  newFocalPoints[1],
                    oldFocalPoints[0], oldFocalPoints[1]);
        return true;
    }
    
    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector){
        //when a new scaling process begins, get the current imageMatrix and 
        //map the points to account for the current zoom level
    
        //the initial points. based on screen location and current scroll pos
        float startX = detector.getFocusX() + getScrollX();
        float startY = detector.getFocusY() + getScrollY();
        oldFocalPoints = new float[]{startX, startY};
    
        //map oldFocalPoints to coordinates of the imageView based on current zoom
        Matrix inverseTransformMatrix = new Matrix();
    
        if(transformMatrix.invert(inverseTransformMatrix))
            inverseTransformMatrix.mapPoints(newFocalPoints, oldFocalPoints);
    
        return true;
    }
    

    出于调试目的,上面图片中的绿点设置为{oldCoordinates[0], oldCoordinates[1]},虽然它不是焦点,但它非常接近。所以看起来虽然我似乎正确地计算了新的焦点(红色圆圈),但它似乎没有被正确应用。谁能发现错误?提前谢谢!

1 个答案:

答案 0 :(得分:3)

经过多次痛苦,我发现了解决方案。这是代码:

@Override
public boolean onScale(ScaleGestureDetector detector) {

    scaleFactor *= detector.getScaleFactor();
    scaleFactor = Math.max(ZOOM_4, Math.min(scaleFactor, ZOOM_LEVEL_0));

    float xDiff = initialFocalPoints[0] - currentFocalPoints[0];
    float yDiff = initialFocalPoints[1] - currentFocalPoints[1];

    transformMatrix.setScale(scaleFactor, scaleFactor, 
                                 currentFocalPoints[0], currentFocalPoints[1]);
    transformMatrix.postTranslate(xDiff, yDiff);    
    child.setImageMatrix(transformMatrix);

    return true;
}

@Override
public boolean onScaleBegin(ScaleGestureDetector detector){

    float startX = detector.getFocusX() + getScrollX();
    float startY = detector.getFocusY() + getScrollY();

    initialFocalPoints = new float[]{startX, startY};

    if(transformMatrix.invert(inverseTransformMatrix))
    inverseTransformMatrix.mapPoints(currentFocalPoints, initialFocalPoints);
    return true;
}

产生差异的线条如下:

float xDiff = initialFocalPoints[0] - currentFocalPoints[0];
float yDiff = initialFocalPoints[1] - currentFocalPoints[1];
transformMatrix.postTranslate(xDiff, yDiff);

答案很简单,只要找出两点之间的差异,并在每次缩放图像时翻译图像视图。