引言:
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);
}
}