做android开发对touch事件是要清晰明了的,如果心存疑问,那么本博客
可以帮你清晰的屡清楚源码是如果实现
onLongClickListener
onDoubleClickListener
onClickListener
并且再次基础上我们可以随意添加我们想要的事件
例如:长按抬起 长按超过三秒 长按移动到view之外等事件
有了这个再也不怕产品的各种触摸事件了
初步了解MotionEvent
public static final int ACTION_DOWN = 0;单点触摸动作
public static final int ACTION_UP = 1;单点触摸离开动作
public static final int ACTION_MOVE = 2;触摸点移动动作
public static final int ACTION_CANCEL = 3;触摸动作取消
public static final int ACTION_OUTSIDE = 4;触摸动作超出边界
public static final int ACTION_POINTER_DOWN = 5;多点触摸动作
public static final int ACTION_POINTER_UP = 6;多点离开动作
//以下是一些非touch事件
public static final int ACTION_HOVER_MOVE = 7;
public static final int ACTION_SCROLL = 8;
public static final int ACTION_HOVER_ENTER = 9;
public static final int ACTION_HOVER_EXIT = 10;
自定义onLongClickListener
API原理
http://www.2cto.com/kf/201402/276490.html
1. 满足一些先决条件。例如:当前视图非禁用状态、当前视图允许点击或者长按(详见 一、onTouchEvent整体结构)之后通过系统反馈的动作来进行判断
ACTION_DOWN:当前是否为滚动视图,如果不是,当前视图先显示为按下状态,且在500毫秒后执行长按操作。
ACTION_MOVE:如果手指移动出当前视图范围内,清理以上设置的所有状态,并且如果长按还没有执行不会触发
ACTION_UP:如果MOVE时没有进行清理,且还没有执行长按操作,执行点击操作(详见 五、ACTION_UP)
ACTION_CANCEL:清理所有状态
仿照api自定义长按事件
在Down的时候开启一个线程然后延迟300ms(长按触发的时间)后执行,然后再UP的时候判断如果按住的时间没有超过了300ms那么代码长按事件没有触发,然后执行连续点击事件的逻辑,同时删除掉Handler队列中的处理长按事件的线程,如果执行了Move事件也需要删除Handler队列里面的长按处理线程。
自定义onClickListener 单击 双击 多击事件
实现多击判断是记录点击的次数,也就是在Down的时候对点击次数+1,在Up的时候开启一个线程来等待是否在短时间内有下一次点击到来。定义了连续点击间隔时间为
private static final long CLICK_SPACING_TIME = 300;
这里利用Handler来让click线程延迟300ms执行,如果在线程还没有开始执行之前又一Down事件来了,那么在Handler的队列中删除这个线程,然后再Up里面重新往Handler里面添加一个线程来执行,这样就完成了间隔时间的等待,线程里面处理逻辑非常简单,就是把点击次数清空,然后回调一共连续点击了多少次。
自定义长按超过n秒事件
在发起长按监听的事件我们通过handler延迟n 毫秒来执行LongTimePressThread线程,在线程中执行回调,并且将
longClickThreeMuch
状态改为true
自定义长按超过n秒且移动到外头的事件
在ACTION_MOVE时,判断移动的点是不是在本view内,并且
longClickThreeMuch
状态为true,那么回调此事件
自定义长按在view 内外部抬起事件
在ACTION_UP时,首先先判断抬起的时间与最开始down的时间有没有超过设定的最大时间,超过了那么就是长按事件的抬起监听,继续判断抬起的点是不是在本view内 然后回调
资源释放 防止内存泄漏
将所有的handler post出去的线程,remove掉
源码
package com.meelive.ingkee.ui.listener;
import android.graphics.Rect;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.util.Calendar;
/**
* Created by walkingmen on 2016/12/17.
* 处理复杂的点击 长按 长按抬起 长按滑动等事件
*/
public class BeautyTouchListener implements View.OnTouchListener {
private static final String TAG = "SHF";
private OnBeautyTouchLisener mOnBeautyTouchLisener;
private long longPressTipTime;
public long getLongPressTipTime() {
return longPressTipTime;
}
public void setLongPressTipTime(long longPressTipTime) {
this.longPressTipTime = longPressTipTime;
}
public void setOnBeautyTouchLisener(OnBeautyTouchLisener onBeautyTouchLisener) {
mOnBeautyTouchLisener = onBeautyTouchLisener;
}
public BeautyTouchListener() {
}
public BeautyTouchListener(OnBeautyTouchLisener onBeautyTouchLisener) {
mOnBeautyTouchLisener = onBeautyTouchLisener;
}
private boolean touchOutside = false;
private boolean touchInSide = false;
private boolean longClickThreeMuch = false;
private boolean haveTip = false;
/**
* ----------------
*/
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 long mLongClickStartTime = -1;
private Handler mBaseHandler = new Handler();
/**
* 长按线程
*/
private LongPressedThread mLongPressedThread;
/**
* 点击等待线程
*/
private ClickPressedThread mPrevClickThread;
/**
* 长按等待三秒的进程
*/
private LongTimePressThread mLongTimePressThread;
@Override
public boolean onTouch(View v, MotionEvent event) {
//获取相对屏幕的坐标,即以屏幕左上角为原点
float x;
float y;
//获取相对屏幕的坐标,即以屏幕左上角为原点
mCurrentInScreenX = (int) event.getRawX();
mCurrentInScreenY = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
haveTip = false;
/**----------------*/
x = event.getRawX();
y = event.getRawY();
if (isInside(v, x, y)) {
touchInSide = true;
touchOutside = false;
} else {
touchInSide = false;
touchOutside = true;
}
Log.i(TAG, "SHF--onTouch---> ACTION_DOWN");
/**----------------*/
//记录Down下时的坐标
mDownInScreenX = (int) event.getRawX();
mDownInScreenY = (int) event.getRawY();
//记录当前点击的时间
mCurrentClickTime = Calendar.getInstance().getTimeInMillis();
//刷新长按的开始时间
mLongClickStartTime = -1;
//点击次数加1