22

我试图让用户触摸图像,然后基本上会显示一个圆形放大镜,这将允许用户更好地选择图像上的某个区域。当用户释放触摸时,放大的部分将消失。这用于几个照片编辑应用程序,我正在尝试实现我自己的版本。我下面的代码确实放大了图像视图的圆形部分,但一旦我松开手指,就不会删除或清除缩放。我目前使用将位图设置为画布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; 
            } 
            });
4

4 回答 4

18

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

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

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

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

mPaint = new Paint();
mPaint.setShader(mShader);
于 2012-12-20T18:51:12.223 回答
6

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

于 2012-12-20T11:01:12.413 回答
3

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

// 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)
    }
}
于 2018-07-19T08:59:24.660 回答
0

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

<com.yourpackage.CodesforMagnifierImageView
     android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/your image" />
于 2017-04-17T05:19:49.160 回答