安卓 ImageView 缩放效果

4

我正在开发一个应用程序,用户将能够对图像进行缩放。但是我需要制作镜头效果,而不是捏合缩放。这意味着当用户单击图像并将手指按在上面一段时间时,右侧会出现放大图像的圆形。它看起来像这样: enter image description here

我查看了下面提供的答案和链接,并得到了以下代码,但它没有起作用:

public class MainActivity extends Activity implements OnTouchListener{
ImageView takenPhoto;
static PointF zoomPos;
Paint shaderPaint;
BitmapShader mShader;
BitmapShader shader;
Bitmap bmp;
Bitmap mutableBitmap;
static Matrix matrix;
Canvas canvas;
static Paint mPaint;
static boolean zooming;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        File file = new File(Environment.getExternalStorageDirectory() + "/Pictures/boxes.jpg");

        String fileString = file.getPath();


        takenPhoto = (ImageView) findViewById(R.id.imageView1);

        bmp = BitmapFactory.decodeFile(fileString);
        mutableBitmap = bmp.copy(Bitmap.Config.ARGB_8888, true);
        takenPhoto.setImageBitmap(mutableBitmap);

        matrix = new Matrix();
        mShader = new BitmapShader(mutableBitmap, TileMode.CLAMP, TileMode.CLAMP); 
        mPaint = new Paint();
        mPaint.setShader(mShader);
        takenPhoto.setOnTouchListener(this);
    }

    private static class ZoomView extends View {



        public ZoomView(Context context) {
            super(context);
        }


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

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





    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        return true;
    }


}

2
喜欢这个图画 :-) - Rob85
这里有很多信息和想法:https://dev59.com/EGsz5IYBdhLWcg3wbHTG - Rob85
此问题在某种程度上是重复的:https://dev59.com/32Yr5IYBdhLWcg3wNHmh - craigts
有人知道为什么它作为放大“刷子效果”而不是镜头工作吗? - Oleksandr Firsov
3个回答

2
我的猜测是:
1. 你需要在ImageView上使用触摸监听器。 2. 你需要有一个画布(在其中绘制缩放后的位图)。
如果你想要的话,你还可以实现OnDragListener,在你拖动手指时更新圆形缩放图像。
我建议你看一下这个链接:Android - 如何对图像的一部分进行圆形缩放/放大?

对于让圆形跟随一个手指移动的问题,您需要在要缩放的图像上设置onDragListener,但效果将是移动一个圆形。要清除绘图,请调用Canvas.drawColor()方法。该方法将重新绘制画布中的每个像素到您想要的颜色。这将使圆形消失。 - Miriana Itani
onTouchListener运行良好。因此,添加onDragListener没有意义。当我使用Canvas.drawColor(0)或canvas.drawColor(Color.TRANSPARENT)时,什么都不会发生 - 缩放点仍然存在。 - Oleksandr Firsov
你尝试过添加invalidate吗? - Miriana Itani
[更新]部分的第一个代码片段中进行更新。当我移动并拿开手指时,我使用了canvas.drawColor()。 - Oleksandr Firsov
这很奇怪。尝试添加到action_up。 - Miriana Itani
显示剩余6条评论

2

经过多天的努力,我在以上回答和其他来源的帮助下,终于成功编写出可完全运行的代码。

为了节约大家的时间,现在将其分享。只需要复制粘贴并稍加编辑即可适应您的目标。

首先,您需要编辑主活动 - 我们将使用自定义ImageView。

 <your.package.name.ZoomView
    android:id="@+id/imageView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

接下来我们需要编辑MainActivity.java文件。只需像ImageView一样使用ZoomView即可。

ImageView takenPhoto;
takenPhoto = (ZoomView) findViewById(R.id.imageView1);

创建ZoomView类并粘贴以下内容:

接下来,创建ZoomView类并将以下内容粘贴:

public class ZoomView extends ImageView {

PointF zoomPos;
boolean zooming;
Matrix matrix;
BitmapShader mShader;
Paint mPaint;

public ZoomView(Context context) {
    super(context);
}

public ZoomView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public ZoomView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
    zoomPos = new PointF();
    zoomPos.x = event.getX();
    zoomPos.y = event.getY();

    matrix = new Matrix();
    mShader = new BitmapShader(MainActivity.mutableBitmap, TileMode.CLAMP, TileMode.CLAMP);
    mPaint = new Paint();
    mPaint.setShader(mShader);

    int action = event.getAction(); 

    switch (action) { 
    case MotionEvent.ACTION_DOWN:
    case MotionEvent.ACTION_MOVE:
        zooming = true;
        this.invalidate();
        break; 
    case MotionEvent.ACTION_UP: 
        zooming = false;
        this.invalidate();
        break;
    case MotionEvent.ACTION_CANCEL:
        zooming = false;
        this.invalidate();
        break; 

    default: 
        break; 
    }
 return true;
}

@Override
protected void onDraw(@NonNull 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);
    }
}
}

现在,您应该有可工作的放大效果。

1
但是圆圈将始终在您的手指下。如果通过更改zoomPos.x和zoomPos.y来更改其位置,则位图将以错误的位置进行缩放。 - user 007

0

一个可能的解决方案是从显示图像的视图中获取Canvas对象。您将需要使用各种运动事件更新Canvas。

在处理这些事件时,使用功能来仅绘制图像的一部分。所列方法是Canvas对象的一部分。至于参数:

Bitmap bitmap   //The image to zoom on
Rectangle src   //A rectangle defining the portion of the image to zoom in on
Rectangle dest  //A rectangle defining where in the View to draw the zoomed portion of your image. 
                //If the size of the rectangles is mismatched, it will zoom.
Paint paint     //The paint object necessary for drawing.

如果您有任何问题,请留言。编程愉快!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接