【Android开发小记--9】触摸事件---实现双指缩放图片
16lz
2021-01-23
关于触摸事件
覆写 onTouchEvent(MotionEvent event) 方法:
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: break; } //以下三种效果都是一样的 System.out.println(event.getAction()); /*老写法*/ System.out.println(event.getActionMasked());/*API 8 以后,Google推荐*/ System.out.println(MotionEventCompat.getActionMasked(event)); /*兼容写法*/ //获取屏幕上的手指数 System.out.println(MotionEventCompat.getPointerCount(event)); //触点坐标 int actionIndex = MotionEventCompat.getActionIndex(event); //多点触摸 if (MotionEventCompat.getPointerCount(event) > 1) { float touchX_1 = MotionEventCompat.getX(event, 0); float touchY_1 = MotionEventCompat.getY(event, 0); float touchX_2 = MotionEventCompat.getX(event, 1); float touchY_2 = MotionEventCompat.getY(event, 1); System.out.println(String.format("touchX_1:%f,touchY_1:%f,touchX_2:%f,touchY_2:%f\n", touchX_1, touchY_1, touchX_2, touchY_2)); } else { //单点触摸 float touchX = MotionEventCompat.getX(event, actionIndex); float touchY = MotionEventCompat.getY(event, actionIndex); System.out.println(touchX + "\t" + touchY); } return super.onTouchEvent(event); }
getAction、getActionMask、getActionIndex区别:
Android用一个32位的整型值表示一次TouchEvent事件,低8位表示touch事件的具体动作,比如按下,抬起,滑动,还有多点触控时的按下,抬起,这个和单点是区分开的,下面看具体的方法:1 getAction:触摸动作的原始32位信息,包括事件的动作,触控点信息
2 getActionMask:触摸的动作,按下,抬起,滑动,多点按下,多点抬起
3 getActionIndex:触控点信息
Matrix 中的post 和pre 和set 方法的区别 以及Canvas中的方法:
post pre set 其实代表了Matrix 中方法变换的次序,pre是向前加入队列执行,post从后面加入队列执行, 而matrix的set方法则会对先前的pre和post操作进行清除,而后再设置它的值。双指缩放图片,并且带拖动回弹居中的效果
这里是使用 Matrix +Bitmap 来进行图片缩放的。
首先,要对布局文件中的 ImageView 设置:
android:scaleType="matrix"
在 MainActivity.java 中,调用 Matrix 的 setScale()、postTranslate()、postScale() 方法来设置图片的移动方式,再调用 ImageView 的 setImageMatrix():
public class MainActivity extends AppCompatActivity { private ImageView imageView; private int screenWidth, screenHeight;//屏幕宽高 private Bitmap bitmap; private Matrix matrix = new Matrix(); private Matrix savedMatrix = new Matrix(); private int mode = 0; private float distance; private float preDistance; private PointF mid = new PointF();//两指中点 Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = MainActivity.this; imageView = (ImageView) findViewById(R.id.imageView); bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); matrix.setScale(0.5f, 0.5f); //显示先缩小一些 center();//缩小后居中 imageView.setImageMatrix(matrix); imageView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { ImageView view = (ImageView) v; switch (event.getAction() & MotionEvent.ACTION_MASK) { //单个手指触摸 case MotionEvent.ACTION_DOWN: mode = 1; break; //两指触摸 case MotionEvent.ACTION_POINTER_DOWN: preDistance = getDistance(event); //当两指间距大于10时,计算两指中心点 if (preDistance > 10f) { mid = getMid(event); savedMatrix.set(matrix); mode = 2; } break; case MotionEvent.ACTION_UP: mode = 0; break; case MotionEvent.ACTION_POINTER_UP: mode = 0; break; case MotionEvent.ACTION_MOVE: //当两指缩放,计算缩放比例 if (mode == 2) { distance = getDistance(event); if (distance > 10f) { matrix.set(savedMatrix); float scale = distance / preDistance; matrix.postScale(scale, scale, mid.x, mid.y);//缩放比例和中心点坐标 } } break; } view.setImageMatrix(matrix); center(); //回弹,令图片居中 return true; } }); } /*获取两指之间的距离*/ private float getDistance(MotionEvent event) { float x = event.getX(1) - event.getX(0); float y = event.getY(1) - event.getY(0); float distance = (float) Math.sqrt(x * x + y * y);//两点间的距离 return distance; } /*使图片居中*/ private void center() { Matrix m = new Matrix(); m.set(matrix); //绘制图片矩形 //这样rect.left,rect.right,rect.top,rect.bottom分别就就是当前屏幕离图片的边界的距离 RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); m.mapRect(rect); float height = rect.height(); float width = rect.width(); float deltaX = 0, deltaY = 0; //屏幕的宽高 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); //获取屏幕分辨率 screenWidth = dm.widthPixels; //屏幕宽度 screenHeight = dm.heightPixels; //屏幕高度 //获取ActionBar的高度 int actionBarHeight = 0; TypedValue tv = new TypedValue(); if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); } //计算Y到中心的距离 if (height < screenHeight) { deltaY = (screenHeight - height) / 2 - rect.top - actionBarHeight; } else if (rect.top > 0) { deltaY = -rect.top; } else if (rect.bottom < screenHeight) { deltaY = imageView.getHeight() - rect.bottom; } //计算X到中心的距离 if (width < screenWidth) { deltaX = (screenWidth - width) / 2 - rect.left; } else if (rect.left > 0) { deltaX = -rect.left; } else if (rect.right < screenWidth) { deltaX = screenWidth - rect.right; } matrix.postTranslate(deltaX, deltaY); } /*取两指的中心点坐标*/ public static PointF getMid(MotionEvent event) { float midX = (event.getX(1) + event.getX(0)) / 2; float midY = (event.getY(1) + event.getY(0)) / 2; return new PointF(midX, midY); }}
这里,令图片居中的 center() 方法:
1.使用Bitmap来获取图片的宽高,再使用矩形 RectF ,以及 Matrix 的 mapRect()方法来得到当前图片的位置;
2.获取屏幕宽高,以及Actionbar的高度;
3.再计算图片中心点到屏幕中心点的距离,进行平移;
具体代码点击
更多相关文章
- android上传图片(同步上传)
- Android实现图片的倒影效果
- checkbox切换选中状态的图片
- [Android官方Demo系列] PageTransformer缩放滑动
- 图片加载库Glide的使用
- Androd之在图片右上角显示红色圆圈里面数字提醒