参考:
https://www.cnblogs.com/devinzhang/archive/2012/02/27/2369942.html
https://www.jianshu.com/p/cafedd319512
https://blog.csdn.net/zhangyalong_android/article/details/69525455
Android 触控事件的核心为onTouchEvent方法,其中用一个32位int来存储动作信息和索引信息,通过简单的与运算和移位运算可以提取出这两个信息,需要用到MotionEvent类的四个常量:
ACTION_MASK = 8(0x00ff) :动作信息掩码,用于截取目标动作信息;
ACTION_MASK_SHIFT = 8(0x00ff) : 截取动作信息时所需移位个数
ACTION_POINTER_INDEX_MASK =65280(0xff00) :高8位的位置信息掩码,用于截取索引信息(索引指的是第几个手指头)
ACTION_POINTER_INDEX_SHIFT= 8(0x00ff) :截取触控索引时所需的移位个数
其中多点触控中常用的几个方法有:
MotionEvent.getAction() //获取触控动作比如ACTION_DOWN
MotionEvent.getPointerCount(); //获取触控点的数量,比如2则可能是两个手指同时按压屏幕
MotionEvent.getPointerId(nID); //对于每个触控的点的细节,我们可以通过一个循环执行getPointerId方法获取索引
MotionEvent.getX(nID); //获取第nID个触控点的x位置
MotionEvent.getY(nID); //获取第nID个点触控的y位置
MotionEvent.getPressure(nID); //LCD可以感应出用户的手指压力,当然具体的级别由驱动和物理硬件决定的
MotionEvent.getDownTime() //按下开始时间
MotionEvent.getEventTime() // 事件结束时间
MotionEvent.getEventTime()-event.getDownTime()); //总共按下时花费时间
几种动作类型:
ACTION_DOWN : 第一个手指按下
ACTION_UP : 最后一个手指离开
ACTION_POINTER_DOWN :非第一个手指按下
ACTION_POINTER_UP : 非最后一个手指离开
ACTION_POINTER_1_DOWN : 这是之前SDK版本所使用的,表示第一个手指按下,它的数值跟ACTION_DOWN是相等的
ACTION_POINTER_2_DOWN:第二根手指按下
ACTION_POINTER_3_DOWN:第三根手指按下
ACTION_POINTER_x_DOWN:第x根手指离开
自己写的Demo:
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
@RequiresApi(api = 3)
public class MainActivity extends AppCompatActivity {
private String TAG = getClass().getSimpleName();
private ImageView imageView;
private GestureDetector gestureDetector;
private int num = 1;
private int downX;
private int downY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView)findViewById(R.id.imageview);
Glide.with(this)
.load("file:///android_asset/images/1.jpg")
.into(imageView);
gestureDetector = new GestureDetector(this,gestureListener);
imageView.setOnClickListener(clickListener);
imageView.setOnTouchListener(touchListener);
}
private View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
num++;
String path = "file:///android_asset/images/"+num%4+".jpg";
Glide.with(MainActivity.this).load(path).into(imageView);
logd("click 事件发生");
}
};
private View.OnTouchListener touchListener = new View.OnTouchListener() {
/**
* Android中触控事件的核心是onTouch事件,用一个32位int来存储动作信息和索引信息,可以使用下面四个常量来提取所需要的信息
* ACTION_MASK = 8(0x00ff) :动作信息掩码,用于截取目标动作信息;
* ACTION_MASK_SHIFT = 8(0x00ff) : 截取动作信息时所需移位个数
* ACTION_POINTER_INDEX_MASK =65280(0xff00) :高8位的位置信息掩码,用于截取索引信息(索引指的是第几个手指头)
* ACTION_POINTER_INDEX_SHIFT= 8(0x00ff) :截取触控索引时所需的移位个数
* 动作类型:
* ACTION_DOWN:第一个手指头按下
* ACTION_UP :最后一个手指离开
* ACTION_POINTER_DOWN :非第一个手指按下
* ACTION_POINTER_UP :非最后一个手指离开
* ACTION_MOVE:手指移动
* ACTION_POINTER_1_DOWN : 这是之前SDK版本所使用的,表示第一个手指按下,它的数值跟ACTION_DOWN是相等的
* ACTION_POINTER_2_DOWN:第二根手指按下
* ACTION_POINTER_3_DOWN:第三根手指按下
* ACTION_POINTER_x_DOWN:第x根手指离开
*/
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
// int action = (motionEvent.getAction() & MotionEvent.ACTION_MASK);
int action = motionEvent.getActionMasked();
int index = motionEvent.getActionIndex();
//这里如果不用GestureDetector的话就得自己根据action的变化来监测手势的变化,这会非常麻烦
//好在Google提供了GestureDetector,由它来监听手势的变化
// int index = (motionEvent.getAction()&MotionEvent.ACTION_POINTER_INDEX_MASK)>>motionEvent.ACTION_POINTER_INDEX_SHIFT;
gestureDetector.onTouchEvent(motionEvent);
switch (action){
//第一个点被按下
case MotionEvent.ACTION_DOWN:
downX = (int)motionEvent.getX();
downY = (int)motionEvent.getY();
logd("Action down事件发生");
break;
//手指移动
case MotionEvent.ACTION_MOVE:
int moveX = (int)motionEvent.getX();
int moveY = (int)motionEvent.getY();
if(Math.abs(moveX-downX)>20&&Math.abs(moveY-downY)>20){
return true;
}
logd("Action move 事件发生");
break;
//最后一个手指离开
case MotionEvent.ACTION_UP:
logd("Action up事件发生");
break;
//非第一个点按下
case MotionEvent.ACTION_POINTER_DOWN:
logd("Action pointer down 事件发生");
break;
//非最后一个点离开
case MotionEvent.ACTION_POINTER_UP:
logd("Action pointer up 事件发生");
break;
case MotionEvent.ACTION_CANCEL:
logd("Action cancle 事件发生");
default:
break;
}
//如果return true表示事件已经被消费,onClick事件不会有响应
return false;
}
};
private void logd(String s) {
Log.d(TAG,s);
// Toast.makeText(this,s,Toast.LENGTH_LONG).show();
}
private GestureDetector.OnGestureListener gestureListener = new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent motionEvent) {
logd("onDown手势");
return false;
}
@Override
public void onShowPress(MotionEvent motionEvent) {
logd("onShowPress手势");
}
@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
logd("onSingleTapUp手势");
return false;
}
@Override
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
logd("onScroll手势");
return false;
}
@Override
public void onLongPress(MotionEvent motionEvent) {
logd("onLongPress手势");
}
@Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
logd("onFling手势");
return false;
}
};
}
layout文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageview"
android:layout_width="200dp"
android:layout_height="200dp"/>
</RelativeLayout>
手势识别类:GestureDetector,只需要调用GestureDetector.onTouchEvent(motionEvent),在传入一个GestureDetector.OnGestureListener,就能够识别几种常用手势。
几种手势动作:
OnDown(MotionEvent e):用户按下屏幕就会触发;
onShowPress(MotionEvent e):如果是按下的时间超过瞬间,而且在按下的时候没有松开或者是拖动的,那么onShowPress就会执行
onLongPress(MotionEvent e):长按触摸屏,超过一定时长,就会触发这个事件
onSingleTapUp(MotionEvent e):从名字也可以看出,一次单独的轻击抬起操作,也就是轻击一下屏幕,立刻抬起来,才会有这个触发,当然,如果除了Down以外还有其它操作,那就不再算是Single操作了,所以也就不会触发这个事件
onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) :滑屏,用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY):在屏幕上拖动事件。无论是用手拖动view,或者是以抛的动作滚动,都会多次触发,这个方法 在ACTION_MOVE动作发生时就会触发