import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
/**
* 双击与单机监听
*/
public class OnDoubleClickListener implements View.OnTouchListener {
private Handler handler = new Handler();
;
private int count = 0;//点击次数
private long firstClick = 0;//第一次点击时间
private long secondClick = 0;//第二次点击时间
private long lastDoubleClick = 0;//上次响应成功时间戳
/**
* 两次点击时间间隔,单位毫秒
*/
private final int totalTimeOne = 250;
private final int totalTimeTwo = 500;
/*双击 响应 间隔*/
private final int timeComplete = 1000;
/**
* 自定义回调接口
*/
private DoubleClickCallback mCallback;
public interface DoubleClickCallback {
void onDoubleClick();
void onClick();
}
public OnDoubleClickListener(DoubleClickCallback callback) {
super();
this.mCallback = callback;
}
/**
* 触摸事件处理
*
* @param v
* @param event
* @return
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getAction()) {//按下
count++;
if (1 == count) {
firstClick = System.currentTimeMillis();//记录第一次点击时间
} else if (2 == count) {
handler.removeCallbacksAndMessages(null);
secondClick = System.currentTimeMillis();//记录第二次点击时间
if (secondClick - firstClick < totalTimeTwo) {//判断二次点击时间间隔是否在设定的间隔时间之内
/*判断 上次按钮生效间隔 */
if (secondClick - lastDoubleClick > timeComplete) {
lastDoubleClick = secondClick;
if (mCallback != null) {
mCallback.onDoubleClick();
}
}
count = 0;
firstClick = 0;
secondClick = 0;
} else {
firstClick = secondClick;
count = 1;
}
}
} else if (MotionEvent.ACTION_UP == event.getAction()) {
if (1 == count) {
long firstUpClick = System.currentTimeMillis();//记录第一次点击时间
long deltaClick = firstUpClick - firstClick;
if (deltaClick < totalTimeOne / 2) {
handler.postDelayed(() -> {
mCallback.onClick();
count = 0;
firstClick = 0;
secondClick = 0;
}, totalTimeOne);
}
}
}
return true;
}
}
Touch无响应问题解决
父布局拦截问题
//父布局 特定情况下返回false 给子布局处理
@Override
public boolean onTouchEvent(MotionEvent event) {
return false;
}
/*子布局 避免 外部抢夺触摸事件 比如ScollerView*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
getParent().requestDisallowInterceptTouchEvent(true);
break;
}
case MotionEvent.ACTION_MOVE: {
break;
}
case MotionEvent.ACTION_UP: {
getParent().requestDisallowInterceptTouchEvent(false);
break;
}
}
return super.dispatchTouchEvent(ev);
}
onTouch & onTouchEvent & dispatchTouchEvent的关系
这里加上笔者的简单解释,方便理解。
- onTouch 级别高于onTouchEvent 返回true会导致 onClickLIstener与onTouchEvent 都无法使用;
- onTouchEvent返回true会导致子控件无法回调onTouch与各种触摸事件;
- dispatchTouchEvent可强制要求父布局释放触摸事件,相当于:onTouchEvent返回false;