安卓实现图片放大缩小,并解决onTouch与onClick冲突

引言:
Matrix可以实现图片的变换,再结合onTouch中的事件,就可以实现图片放大缩小功能。而我的这个功能基于单击某个条目实现对该条目对应图片的缩放,所以单独写了一个活动,并且只点击图片,而不进行拖放,需要实现销毁活动的功能。于是,产生了onTouch与onClick冲突,这里我选择了判断操作时间来控制是否响应点击事件。详细实现,见以下代码和注释。

demo:

package com.example.test2.activities;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

import com.example.test2.R;

public class PicActivity extends AppCompatActivity implements View.OnTouchListener, View.OnClickListener {

    private ImageView mImageView;
    private Matrix matrix;
    private Matrix savedMatrix;
    private PointF startPoint;
    private PointF midPoint;
    private static final int NONE=0;
    private static final int DRAG=1;
    private static final int ZOOM=2;
    private int mode;
    private float oriDis;
    private float newDis;
    private float scale;
    private boolean isNotReactClick; //是否选择不响应点击事件,默认为false
    private long startTime;  //用触摸时长来决定是否相应点击事件
    private long endTime;

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pic_layout);
        initView();
        Intent intent=getIntent();
        int data=intent.getIntExtra("drawable_id",1);
        mImageView.setImageResource(data);
        mImageView.setOnClickListener(this);
        mImageView.setOnTouchListener(this);
    }

    private void initView() {
        mImageView=findViewById(R.id.pic_layout_img);
        matrix=new Matrix();
        savedMatrix=new Matrix();
        startPoint=new PointF();
        midPoint=new PointF();
        mode=NONE;
        oriDis=1f;
        newDis=1f;
        scale=newDis/oriDis;
        isNotReactClick =false;
        startTime=0;
        endTime=0;
    }

    @Override
    public void onClick(View v) {
        switch(v.getId()){
            case R.id.pic_layout_img:
                finish();
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()&MotionEvent.ACTION_MASK){
            case MotionEvent.ACTION_DOWN:
                matrix.set(mImageView.getImageMatrix());
                savedMatrix.set(matrix);
                startPoint.set(event.getX(),event.getY());
                /*
                 *一个触点按下后,记录下初始的矩阵和点的坐标
                 */
                //Log.w("TAG_MOVE_DOWN",matrix.equals(savedMatrix)+"");
                mode=DRAG;
                isNotReactClick =false;
                startTime=System.currentTimeMillis();
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                oriDis=distance(event);
                //此判断是为了避免手指造成的触控点数异常
                if(oriDis>12.5f){
                    savedMatrix.set(matrix);
                    midPoint=middle(event);
                    mode=ZOOM;
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                mode=NONE;
                break;
            case MotionEvent.ACTION_UP:
                mode=NONE;
                endTime=System.currentTimeMillis();
                Log.w("tag",""+(endTime-startTime));
                if(endTime-startTime<=250){
                    //触摸事件短于250ms我理解为点击,自定义的
                    isNotReactClick =false;
                }else{
                    isNotReactClick =true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if(mode==DRAG){
                    /*
                     * 经过调试,我发现了为什么要再次
                     * 使matrix等于savedmatix
                     * 因为每次变换是在最开始的按下点基础上变换的
                     * savedMatrix的值与startPoint保持更新同步
                     */
                    //Log.w("TAG_MOVE1",matrix.equals(savedMatrix)+"");
                    matrix.set(savedMatrix);
                    //Log.w("TAG_MOVE2",matrix.equals(savedMatrix)+"");
                    matrix.postTranslate(event.getX()-startPoint.x,event.getY()-startPoint.y);
                    //Log.w("TAG_MOVE3",matrix.equals(savedMatrix)+"");
                }else if(mode==ZOOM){
                    newDis=distance(event);
                    if(newDis>12.5f){
                        matrix.set(savedMatrix);
                        scale=newDis/oriDis;
                        matrix.postScale(scale,scale,midPoint.x,midPoint.y);
                    }
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
        }
        mImageView.setImageMatrix(matrix);
        return isNotReactClick;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);

    }

    private float distance(MotionEvent event){
        float x=event.getX(0)+event.getX(1);
        float y=event.getY(0)+event.getY(1);
        return (float) StrictMath.sqrt(x*x+y*y);
    }

    private PointF middle(MotionEvent event){
        float x=event.getX(0)+event.getX(1);
        float y=event.getY(0)+event.getY(1);
        return new PointF(x/2,y/2);
    }
}

发布了51 篇原创文章 · 获赞 68 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/tran_sient/article/details/104127112