背景:
随着移动端的快速发展,实体按键已基本被触摸屏所取代,使用者和手机的信息交流,依赖于屏幕。屏幕不仅作为一个显示器,同样兼顾着输入设备,拥有输入输出两种功能,雌雄同体。
功能:点击,是屏幕使用最多的时候,系统提供的单击监听
public void setOnClickListener(@Nullable OnClickListener l) ,
如果需要双击,就需要通过手势监听来实现:GestureDetector
GestureDetector gestureDetector = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDoubleTap(MotionEvent e) { //双击 clickEvent(e, true); return super.onDoubleTap(e); } @Override public boolean onSingleTapConfirmed(MotionEvent e) { //单击 clickEvent(e, false); return super.onSingleTapConfirmed(e); } @Override public boolean onSingleTapUp(MotionEvent e) { return super.onSingleTapUp(e); } @Override public void onLongPress(MotionEvent e) { super.onLongPress(e); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return super.onScroll(e1, e2, distanceX, distanceY); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return super.onFling(e1, e2, velocityX, velocityY); } @Override public void onShowPress(MotionEvent e) { super.onShowPress(e); } @Override public boolean onDown(MotionEvent e) { return super.onDown(e); } @Override public boolean onDoubleTapEvent(MotionEvent e) { return super.onDoubleTapEvent(e); } @Override public boolean onContextClick(MotionEvent e) { return super.onContextClick(e); } });
view.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return gestureDetector.onTouchEvent(event); } });
//常见的两种回调
GestureDetector.SimpleOnGestureListener://简单的监听,已实现双击监听回调
GestureDetector.OnDoubleTapListener://双击监听
这是常见的手势监听,来完成。
但是这种监听是不支持时间订制,也就是双击间距和单击回调的时间机制,导致满足不了一些订制要求
解决方案:
我们可以通过模拟点击,来完成双击和单击,点击最核心是手势按下屏幕和离开,至于在屏幕上滑动MOVING,这些可以忽略,ACTION_DOWN到ACTION_UP的时间差,
接下来我们通过代码来完成模拟
/** * @author :woniu * @date:2022/4/27-17:56 * @wiki: * @projectName:MyApplication * @FileName:ViewTouchManager * @descp: */ public class ViewTouchManager { private static volatile ViewTouchManager manager; private long mClickTime = 0; private boolean clickEnable = false; private boolean doubleClickEnable = false; private long doubleClickTime = 0; private boolean moving = false; private long lasTime = 0; private int clickCount = 0; private final int MSG_CLICK = 0x101;//点击消息 private final int MSG_DOUBLE = 0x102;//双极性消息 private MyHandler myHandler; private SimpleOnClickListener simpleOnClickListener; private MotionEvent motionEvent; private boolean doubleClick = false; public static ViewTouchManager getInstance() { if (manager == null) manager = new ViewTouchManager(); return manager; } public ViewTouchManager setClickTime(boolean clickEnable, long clickTime) { this.clickEnable = clickEnable; this.mClickTime = clickTime; return this; } public ViewTouchManager setOnDoubleClickTime(boolean clickEnable, long clicktime) { this.doubleClickEnable = clickEnable; this.doubleClickTime = clicktime; return this; } public ViewTouchManager addClickListener(View view, SimpleOnClickListener simpleOnClickListener) { this.simpleOnClickListener = simpleOnClickListener; if (view == null) return this; if (myHandler == null) { myHandler = new MyHandler(); } view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { motionEvent = event; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: moving = false; lasTime = System.currentTimeMillis(); break; case MotionEvent.ACTION_CANCEL: { } break; case MotionEvent.ACTION_UP: { long newTime = System.currentTimeMillis(); if (!moving) { moving = false; doubleClick = false; long clicKTime = newTime - lasTime; //双击 if (clicKTime < doubleClickTime && doubleClickEnable) { clickCount++; if (clickCount == 2) { //双击 doubleClick = true; clickCount = 0; if (doubleClickEnable && simpleOnClickListener != null) { simpleOnClickListener.onDoubleClick(event); } } } if (clicKTime < mClickTime) { myHandler.sendEmptyMessageDelayed(MSG_CLICK, doubleClickEnable ? doubleClickTime : mClickTime); } lasTime = newTime; } } break; case MotionEvent.ACTION_MOVE: { // moving = true; } break; } return true; } }); return this; } public interface SimpleOnClickListener { public void onDoubleClick(MotionEvent event); public void onClick(MotionEvent event); } private class MyHandler extends Handler { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case MSG_CLICK: { if (!doubleClick && clickCount != 2) { //单击行为 clickCount = 0; if (clickEnable && simpleOnClickListener != null) { simpleOnClickListener.onClick(motionEvent); } } else if (!doubleClickEnable && clickEnable) { if (clickEnable && simpleOnClickListener != null) { simpleOnClickListener.onClick(motionEvent); } } } break; } } } }