Android处理touch事件
Android事件处理机制是基于Listener实现的,比如触摸屏相关的事件,就是通过onTouchListener实现;
所有View的子类都可以通过setOnTouchListener()、setOnKeyListener()等方法来添加对某一类事件的Listener;
Listener一般以Interface的方式来提供,其中包含一个或多个abstract方法,我们需要实现这些方法来完成onTouch()、onKey()等操作。这样,程序便可以在特定的事件被dispatch到该view的时候,通过callback函数给予适当的响应。
当用户触摸屏幕的时候,会产生许多手势,可以通过下列方式接收事件处理:
1.View类有个View.onTouchListener内部接口,可以通过重写它的onTouch(View v, MotionEvent event)方法,处理一些在该控件中触发的touch事件;
2.也可以通过重写Activity的onTouchEvent方法;
3.通过Android sdk提供的GestureDetector类
onTouch()方法:
当一个View绑定了OnTouchListener后,当有Touch事件触发时,就会调用onTouch方法。当把手放到View上后,onTouch方法被一遍一遍的调用
用法示例1: 在activity中使用
package xxxx;
import android.os.Bundle;
import android.app.Activity;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;
public class MainActivity extends Activity {
//声明ImageView对象
private ImageView testImg = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//ImageView对象
testImg=(ImageView)super.findViewById(R.id.img);
//注册OnTouch监听器
testImg.setOnTouchListener(new ImgOnTouchListener());
}
//OnTouch监听器
private class ImgOnTouchListener implements OnTouchListener{
@Override
public boolean onTouch(View v, MotionEvent event){
/*
do things
*/
return true;
}
}
}
用法示例2:控件继承
package xxxx;
import android.content.Context;
import android.os.Bundle;
import android.app.Activity;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;
import android.util.AttributeSet;
public class TestImg extends ImageView implements OnTouchListener {
// 构造函数
public TestImg(Context context) {
super(context);
}
public TestImg(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 重写onTouch
@Override
public boolean onTouch(View v, MotionEvent event) {
/* do things */
return true;
}
}
onTouchEvent()方法:
重写了Activity的onTouchEvent方法后,当屏幕有Touch事件时,此方法就会被调用。当把手放到Activity上时,onTouchEvent方法会一遍一遍的被调用
用法示例
@Override
public boolean onTouchEvent(MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
// do things
break;
case MotionEvent.ACTION_MOVE:
// do things
break;
case MotionEvent.ACTION_UP:
// do things
break;
}
return true;
GestureDetector:
在onTouch()/onTouchEvent()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector * 来分析是否有合适的callback函数来处理用户的手势
GestureDetector这个类对外提供了两个接口和一个外部类
接口:OnGestureListener,OnDoubleTapListener,OnContextClickListener(不常用)
内部类:SimpleOnGestureListener
用法示例1:GestureDetector.OnGestureListener
package xxxx;
import android.content.Context;
import android.os.Bundle;
import android.app.Activity;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;
import android.view.GestureDetector;
public class TestImg extends ImageView {
private GestureDetector mGestureListener;
// 构造函数
public TestImg(Context context) {
super(context);
}
public TestImg(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureListener = new GestureDetector(context, new GestureListener());
}
// onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
/* do things */
return mGestureListener.onTouchEvent(event); // 或者使用onTouch
}
private class GestureListener implements GestureDetector.OnGestureListener {
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
}
}
用法示例2:GestureDetector.OnDoubleTapListener
package xxxx;
import android.content.Context;
import android.os.Bundle;
import android.app.Activity;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;
import android.view.GestureDetector;
public class TestImg extends ImageView {
private GestureDetector mGestureListener;
// 构造函数
public TestImg(Context context) {
super(context);
}
public TestImg(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureListener = new GestureDetector(context, new GestureListener());
mGestureListener.setOnDoubleTapListener(new DoubleTapListener());
}
// onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
/* do things */
return mGestureListener.onTouchEvent(event); // 或者使用onTouch
}
private class GestureListener implements GestureDetector.OnGestureListener {
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
}
private class DoubleTapListener implements GestureDetector.OnDoubleTapListener {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return false;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
return false;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
}
}
用法示例3:GestureDetector. SimpleOnGestureListener
import android.content.Context;
import android.os.Bundle;
import android.app.Activity;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;
import android.view.GestureDetector;
public class TestImg extends ImageView {
private GestureDetector mGestureListener;
// 构造函数
public TestImg(Context context) {
super(context);
}
public TestImg(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureListener = new GestureDetector(context, new SimpleGestureListener());
}
// onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
/* do things */
return mGestureListener.onTouchEvent(event); // 或者使用onTouch
}
public class SimpleGestureListener extends GestureDetector.SimpleOnGestureListener {
/*OnGestureListener*/
// onDown:用户按下屏幕就会触发,在其他的事件前面
@Override
public boolean onDown(MotionEvent e) {
return false;
}
// onShowPress:用户收到onDown事件,100ms后,还没有拖动或者松开,那么onShowPress就会执行。具体时间可以参照GestureDetector源码
@Override
public void onShowPress(MotionEvent e) {
}
// onSingleTapUp:用户手指松开(UP事件)的时候如果没有执行onScroll()和onLongPress()这两个回调的话,就会回调这个,说明这是一个点击抬起事件,但是不能区分是否双击事件的抬起。
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
// onScroll:在屏幕上拖动事件。无论是用手拖动view,或者是以抛的动作滚动,都会多次触发,这个方法,在ACTION_MOVE动作发生时就会触发
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
// onLongPress:长按触摸屏,超过一定时长,就会触发这个事件。源码里是收到onDown,500ms后
@Override
public void onLongPress(MotionEvent e) {
}
// onFling:滑屏,用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
/*OnDoubleTapListener*/
// onSingleTapConfirmed:单击事件。用来判定该次点击是SingleTap而不是DoubleTap,如果连续点击两次就是DoubleTap手势,如果只点击一次,系统等待一段时间后没有收到第二次点击则判定该次点击为SingleTap而不是DoubleTap,
// 然后触发SingleTapConfirmed事件。触发顺序是:OnDown->OnsingleTapUp->OnsingleTapConfirmed
// onSingleTapUp和onSingleTapConfirmed的区别是:onSingleTapUp,只要手抬起就会执行,而onSingleTapConfirmed,如果双击的话,则onSingleTapConfirmed不会执行。
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return false;
}
// onDoubleTap:双击事件
// 在第二下点击时,先触发OnDoubleTap,然后再触发OnDown(第二次点击)
@Override
public boolean onDoubleTap(MotionEvent e) {
return false;
}
// onDoubleTapEvent:双击间隔中发生的动作。指触发onDoubleTap以后,在双击之间发生的其它动作,包含down、up和move事件
// 在触发OnDoubleTap以后,就开始触发onDoubleTapEvent了,onDoubleTapEvent后面的数字代表了当前的事件,0指ACTION_DOWN,1指ACTION_UP,2 指ACTION_MOVE
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
/*OnContextClickListener*/
@Override
public boolean onContextClick(MotionEvent e) {
return false;
}
}
}
Touch事件的传递:
在一个Activity里面放一个控件的实例c,并且这个c的属性设定为march_parent
当把手放到屏幕上时,首先控件c响应Touch事件,执行onTouch方法。
如果onTouch返回值为true,表示这个Touch事件被onTouch方法处理完毕,不会把Touch事件再传递给Activity
也就是说onTouchEvent方法不会被调用,当把手放到屏幕上后,onTouch方法会被一遍一遍的调用
如果onTouch返回值为false,表示这个Touch事件没有被c完全处理,onTouch返回以后,Touch事件被传递给Activity,
onTouchEvent方法调用,当把手放到屏幕上后,onTouch方法调用一次后,onTouchEvent方法被一遍一遍的调用
参考:
https://blog.csdn.net/lc_miao/article/details/78274840
https://blog.csdn.net/carson_ho/article/details/54136311
https://blog.csdn.net/harvic880925/article/details/39520901