android自定义OnTouchEvent处理长按,单击,双击,多击事件和Touch

        以前一直都是看别人的的文章,自己从来还没写过,这次还是第一次写文章,最近项目中遇到个问题需要处理多次连续点击事件,所以在这里分享出来,效果基本实现了,但是不知道好不好,希望大家看看,有什么不对的地方指出来。

       android本身自带的事件只能处理单击、长按事件,对于双击事件则需要通过手势来判断(参考GestureDetector),我今天在这里实现的方案主要是通过重写OnTouch事件是来实现,首先大家必须了解android的Touch事件,这里不去研究OnTouch事件和OnClick以及OnLongClick的机制了,也不去研究OnTouch的DOWN,MOVE,UP等事件了,相信大家对这方面有一定的了解了,好了进入正题。

     1.连续点击事件  要实现多击判断我的思路是记录点击的次数,也就是在Down的时候对点击次数+1,在Up的时候开启一个线程来等待是否在短时间内有下一次点击到来。所以我定义了连续点击间隔时间为

     private static final long CLICK_SPACING_TIME = 300;

     这里利用Handler来让这个线程延迟300ms执行,如果在线程还没有开始执行之前又一Down事件来了,那么我在Handler的队列中删除这个线程,然后再Up里面重新往Handler里面添加一个线程来执行,这样就完成了间隔时间的等待,线程里面处理逻辑非常简单,就是把点击次数清空,然后回调一共连续点击了多少次。

  

public class ClickPressedThread implements Runnable{

@Override

public void run() {

mClickCount = 0;

}

}

2.长按事件 

        处理长按事件和连续点击事件思路相同,不同的是在Down的时候我开启一个线程然后延迟500ms(长按触发的时间)后执行,然后再UP的时候我判断如果按住的时间没有超过了500ms那么代码长按事件没有触发,然后执行连续点击事件的逻辑,同时删除掉Handler队列中的处理长按事件的线程,如果执行了Move事件也需要删除Handler队列里面的长按处理线程。

完整代码如下:

      


import java.util.Calendar;


import android.os.Handler;

import android.view.MotionEvent;

import android.view.View;

import android.view.View.OnTouchListener;


public class EasyTouchListener implements OnTouchListener{

private static final long CLICK_SPACING_TIME = 300;

private static final long LONG_PRESS_TIME = 500;

/**

* 当前触摸点相对于屏幕的坐标

*/

private int mCurrentInScreenX;

private int mCurrentInScreenY;

/**

* 触摸点按下时的相对于屏幕的坐标

*/

private int mDownInScreenX;

private int mDownInScreenY;

/**

* 点击次数

*/

private int mClickCount = 0;

/**

* 当前点击时间

*/

private long mCurrentClickTime;

private Handler mBaseHandler = new Handler();

/** 

* 长按线程

*/

private LongPressedThread mLongPressedThread;

/**

* 点击等待线程

*/

private ClickPressedThread mPrevClickThread;

@Override

public boolean onTouch(View v, MotionEvent event) {

//获取相对屏幕的坐标,即以屏幕左上角为原点

mCurrentInScreenX = (int)event.getRawX();

mCurrentInScreenY = (int)event.getRawY();

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

//记录Down下时的坐标

mDownInScreenX = (int)event.getRawX();

mDownInScreenY = (int)event.getRawY();

//记录当前点击的时间

mCurrentClickTime = Calendar.getInstance().getTimeInMillis();

//点击次数加1

mClickCount++;

//取消上一次点击的线程

if(mPrevClickThread != null){

mBaseHandler.removeCallbacks(mPrevClickThread);

}

mLongPressedThread = new LongPressedThread();

mBaseHandler.postDelayed(mLongPressedThread,LONG_PRESS_TIME);

break;

case MotionEvent.ACTION_MOVE: {

mClickCount = 0; // 只要移动了 就没有点击事件了

//取消注册的长按事件

mBaseHandler.removeCallbacks(mLongPressedThread);

break;

}

case MotionEvent.ACTION_UP: {

if(!this.isMoved()){

//如果按住的时间超过了长按时间,那么其实长按事件已经出发生了,这个时候把数据清零

if(Calendar.getInstance().getTimeInMillis() - mCurrentClickTime <= LONG_PRESS_TIME){

//取消注册的长按事件

mBaseHandler.removeCallbacks(mLongPressedThread);

mPrevClickThread = new ClickPressedThread();

mBaseHandler.postDelayed(mPrevClickThread,CLICK_SPACING_TIME);

}

}else{

//UP的时候Move过

}

break;

}

default : break;

}

return true;

}

/**

* 判断是否移动

* @return

*/

private boolean isMoved(){

//允许有5的偏差 在判断是否移动的时候

if(Math.abs(mDownInScreenX - mCurrentInScreenX) <= 5 && Math.abs(mDownInScreenY - mCurrentInScreenY) <= 5 ){

return false;

}else{

return true;

}

}

public class LongPressedThread implements Runnable{

@Override

public void run() {

//这里处理长按事件

mClickCount = 0;

}

}

public class ClickPressedThread implements Runnable{

@Override

public void run() {

//这里处理连续点击事件 mClickCount 为连续点击的次数

mClickCount = 0;

}

}

}

PS:吐槽下第一次写博客保存的时候就遇到503,504了 衰!!!!

你可能感兴趣的:(android自定义OnTouchEvent处理长按,单击,双击,多击事件和Touch)