【问题标题】:Android - How to circular zoom/magnify part of image?Android - 如何循环缩放/放大图像的一部分?
【发布时间】:2012-12-01 14:47:36
【问题描述】:

我试图让用户触摸图像,然后基本上会显示一个圆形放大镜,这将允许用户更好地选择图像上的某个区域。当用户释放触摸时,放大的部分将消失。这用于几个照片编辑应用程序,我正在尝试实现我自己的版本。我下面的代码确实放大了图像视图的圆形部分,但一旦我松开手指,就不会删除或清除缩放。我目前使用canvas = new Canvas(bitMap); 将位图设置到画布,然后使用takenPhoto.setImageBitmap(bitMap); 设置图像视图我不确定我是否以正确的方式进行操作。 onTouch 代码如下:

zoomPos = new PointF(0,0);
        takenPhoto.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                 int action = event.getAction(); 
                    switch (action) { 
                        case MotionEvent.ACTION_DOWN: 
                            zoomPos.x = event.getX();
                            zoomPos.y = event.getY();
                            matrix.reset();
                            matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
                            shader.setLocalMatrix(matrix);
                            canvas.drawCircle(zoomPos.x, zoomPos.y, 20, shaderPaint);
                            takenPhoto.invalidate();
                            break; 
                        case MotionEvent.ACTION_MOVE: 
                            zoomPos.x = event.getX();
                            zoomPos.y = event.getY();
                            matrix.reset();
                            matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
                            canvas.drawCircle(zoomPos.x, zoomPos.y, 20, shaderPaint);
                            takenPhoto.invalidate();
                            break; 
                        case MotionEvent.ACTION_UP:   
                            //clear zoom here?

                            break; 
                        case MotionEvent.ACTION_CANCEL: 
                            break; 
                        default: 
                            break; 
            }
                    return true; 
            } 
            });

【问题讨论】:

  • 我不知道我是否理解正确,但是您是在问如何清除图像上的缩放效果?为什么不将原始图像保存在单独的位图中。当用户使用缩放并且是时候摆脱放大镜效果时,使用原始位图并在画布上重新绘制它,从而使用缩放擦除图像。
  • 不,我没有在图像视图上看到放大圈。您能否分享更多内容或代码在哪里工作?
  • 我还需要在画廊中心的透明覆盖框架中缩放图像,因此无论图像通过哪个被缩放,请建议

标签: android android-canvas android-imageview touch-event zooming


【解决方案1】:

有人要求固定放大镜位置,我试验了一下,想出了解决办法:

// bitmapWidth is the width of bitmap used for BitmapShader
// bitmapHeight is the height of bitmap used for BitmapShader
// canvasWidth is the width of canvas where the zoom touch events are tracked (usually has the same image as shader but can be different size)
// canvasHeight is the height of canvas where the zoom touch events are tracked
// touchPoint is the point on the canvas which area should be shown in zoom circle
// fixedZoomPoint is the center of the zoom circle (different from touch point)
// ZOOM_SCALE is the zooming ratio (e.g.: 2f)
// ZOOM_RADIUS is the radius of the zoom circle

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    if (zooming) {
        val widthRatio = bitmapWidth / canvasWidth // This can be omitted if 1.0
        val heightRatio = bitmapHeight / canvasHeight // This can be omitted if 1.0
        matrix.reset()
        matrix.postScale(ZOOM_SCALE, ZOOM_SCALE, touchPoint.x * widthRatio, touchPoint.y * heightRatio)
        matrix.postTranslate(fixedZoomPoint.x - touchPoint.x * widthRatio, fixedZoomPoint.y - touchPoint.y * heightRatio)
        paint.getShader().setLocalMatrix(matrix)
        drawCircle(fixedZoomPoint.x, fixedZoomPoint.y, ZOOM_RADIUS, paint)
    }
}

【讨论】:

  • 虽然这似乎朝着正确的方向发展,但我仍然遇到放大部分显示的图像略微偏移的问题。偏移量似乎是相对的,并且取决于点的坐标,因为触摸点越靠近图像底部,偏移量就越差。
【解决方案2】:

您可以通过使用自定义图像视图来实现它,在您的包中创建一个类 CodesforMagnifierImageView.java。您可以在CodesforMagnifier.java 看到相应类的代码,只需在布局文件中使用以下代码代替图像视图

<com.yourpackage.CodesforMagnifierImageView
     android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/your image" />

【讨论】:

    【解决方案3】:

    调整您的代码后,我能够使用以下方法。

    在 onTouch 函数中,设置一个全局点来确定用户触摸的位置,并设置一个布尔值来指示缩放当前是否处于活动状态:

    @Override
    public boolean onTouch(View view, MotionEvent event) {
    
        int action = event.getAction(); 
    
        zoomPos.x = event.getX();
        zoomPos.y = event.getY();
    
        switch (action) { 
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:
            zooming = true;
            this.invalidate();
            break; 
        case MotionEvent.ACTION_UP:   
        case MotionEvent.ACTION_CANCEL:
            zooming = false;
            this.invalidate();
            break; 
    
        default: 
            break; 
        }
    
        return true; 
    }
    

    然后,在 onDraw 方法中,您使用您的代码来绘制放大部分:

    @Override
    protected void onDraw(Canvas canvas) {
    
        super.onDraw(canvas);
    
        if (zooming) {
            matrix.reset();
            matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
            mPaint.getShader().setLocalMatrix(matrix);
    
            canvas.drawCircle(zoomPos.x, zoomPos.y, 100, mPaint);
        }
    }
    

    请注意,对于着色器,我使用了here 所述的位图着色器,它是通过以下方式创建的:

    mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
    mShader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);
    
    mPaint = new Paint();
    mPaint.setShader(mShader);
    

    【讨论】:

    • @qzikl,您能详细说明一下吗?或者如果你可以写在哪里声明 onDraw 方法以及这里的矩阵是什么?
    • 嘿,感谢上面的代码。有没有办法在某个固定位置显示放大的缩放视图?
    • 画圆的时候是这样的:canvas.drawCircle(FIXED_POS_X, FIXED_POS_Y, 100, mPaint);
    • 这个答案,虽然它确实缩放了图像的位置,但似乎没有在正确的位置缩放。要么就是这样,要么还有更多。我注意到该站点上的一些答案/问题引用了此答案中的代码,其中许多具有相同的问题,即放大倍数中的点偏移。所以如果你触摸 100,100,它实际上放大到 200,200(任意数字)
    • @tronious 确实如此。如何解决?你想清楚了吗?
    【解决方案4】:

    恢复对图像所做的任何更改的最佳方法是从源文件重新加载图像。或者,在转换开始之前,在MotionEvent.ACTION_UP 加载原始矩阵期间保留原始矩阵变量的副本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-12
      • 1970-01-01
      • 2013-05-29
      • 2017-11-20
      • 1970-01-01
      • 1970-01-01
      • 2021-10-08
      相关资源
      最近更新 更多