一、双击监听
既可以监听单击,又可以监听双击。
*** 点击加双击监听*/public abstract class DoubleClickListener implements View.OnClickListener {long mLastTime;@Overridepublic void onClick(final View view) {long nowTime = System.currentTimeMillis();view.removeCallbacks(runnable);//第一次点击,存下时间,等待下次点击if ((nowTime - mLastTime) < 350) {//双击doubleListener(view);} else {view.postDelayed(runnable, 350);}mLastTime = nowTime;}Runnable runnable = new Runnable() {@Overridepublic void run() {singleListener();}};protected abstract void singleListener();protected abstract void doubleListener(View view);}
二、重复点击处理
2.1 kotlin 扩展函数处理
***https://www.jianshu.com/p/7118226ecba9* 设置延迟时间的View扩展* @param delay Long 延迟时间,默认600毫秒* @return T*/fun <T : View> T.withTrigger(delay: Long = 600): T {triggerDelay = delayreturn this}/**** 点击事件的View扩展* @param block: (T) -> Unit 函数* @return Unit*/fun <T : View> T.click(block: (T) -> Unit) = setOnClickListener {block(it as T)}/**** 带延迟过滤的点击事件View扩展* @param delay Long 延迟时间,默认600毫秒* @param block: (T) -> Unit 函数* @return Unit*/fun <T : View> T.clickWithTrigger(time: Long = 600, block: (T) -> Unit){triggerDelay = timesetOnClickListener {if (clickEnable()) {block(it as T)}}}private var <T : View> T.triggerLastTime: Longget() = if (getTag(1123460103) != null) getTag(1123460103) as Long else -601set(value) {setTag(1123460103, value)}private var <T : View> T.triggerDelay: Longget() = if (getTag(1123461123) != null) getTag(1123461123) as Long else 600set(value) {setTag(1123461123, value)}private fun <T : View> T.clickEnable(): Boolean {var flag = falseval currentClickTime = System.currentTimeMillis()if (currentClickTime - triggerLastTime >= triggerDelay) {flag = truetriggerLastTime = currentClickTime}return flag}/**** 带延迟过滤的点击事件监听,见[View.OnClickListener]* 延迟时间根据triggerDelay获取:600毫秒,不能动态设置*/interface OnLazyClickListener : View.OnClickListener {override fun onClick(v: View?) {if (v?.clickEnable() == true) {onLazyClick(v)}}fun onLazyClick(v: View)}
使用示例:
btn_click_all_one.clickWithTrigger {Toast.makeText(this, "hai", Toast.LENGTH_SHORT).show()}btn_click_all_two.withTrigger().click {Toast.makeText(this, "hello", Toast.LENGTH_SHORT).show()}
2.2 java 处理
2.2.1 自定义抽象函数,可以同时监听单击和重复点击
/*** @author : Lss Administrator* @FileName: CustomClickListener* @e-mail : kiwilss@163.com* @time : 2020/12/17* @desc : {https://segmentfault.com/a/1190000016442998}*/public abstract class CustomClickListener implements View.OnClickListener {private long mLastTime;private long mTimeInterval = 1000L;public CustomClickListener() {}public CustomClickListener(long mTimeInterval) {this.mTimeInterval = mTimeInterval;}@Overridepublic void onClick(View view) {long nowTime = System.currentTimeMillis();if (nowTime - mLastTime > mTimeInterval) {//单次点击onSingleClick(view);mLastTime = nowTime;} else {//快速点击onFastClick(view);}}protected abstract void onSingleClick(View view);protected void onFastClick(View view) {}}
使用示例:
btn_click_all_three.setOnClickListener(object : CustomClickListener() {override fun onSingleClick(view: View?) {Toast.makeText(this@ClickAllActivity, "单击", Toast.LENGTH_SHORT).show()}override fun onFastClick(view: View?) {super.onFastClick(view)Toast.makeText(this@ClickAllActivity, "快速点击", Toast.LENGTH_SHORT).show()}})
2.2.2 工具类判断
有局限,对多个控件使用时,相当于一个控件。
/*** @author : Lss Administrator* @FileName: ClickUtils* @e-mail : kiwilss@163.com* @time : 2020/12/17* @desc : {点击限制,只能对一个控件使用,多个控件使用时会在1s内都无法点击}*/public class ClickUtils {private static final int MIN_DELAY_TIME = 1000; // 两次点击间隔不能少于1000msprivate static long lastClickTime;public static boolean clickEnable() {boolean flag = false;long currentClickTime = System.currentTimeMillis();if ((currentClickTime - lastClickTime) >= MIN_DELAY_TIME) {flag = true;}lastClickTime = currentClickTime;return flag;}}
对多个控件单独设置:
public final class XClickUtil {/*** 最近一次点击的时间*/private static long mLastClickTime;/*** 最近一次点击的控件ID*/private static int mLastClickViewId;/*** 是否是快速点击** @param v 点击的控件* @param intervalMillis 时间间期(毫秒)* @return true:是,false:不是*/public static boolean isFastDoubleClick(View v, long intervalMillis) {int viewId = v.getId();long time = System.currentTimeMillis();long timeInterval = Math.abs(time - mLastClickTime);if (timeInterval < intervalMillis && viewId == mLastClickViewId) {return true;} else {mLastClickTime = time;mLastClickViewId = viewId;return false;}}}
2.2.3 使用代理
/*** 代理模式* https://www.jianshu.com/p/dadebb8c3a0e*/public class ClickProxy implements View.OnClickListener {private View.OnClickListener origin;private long lastclick = 0;private long timems = 1000; //msprivate IAgain mIAgain;public ClickProxy(View.OnClickListener origin, IAgain again) {this.origin = origin;this.mIAgain = again;}public ClickProxy(View.OnClickListener origin, long timems, IAgain again) {this.origin = origin;this.mIAgain = again;this.timems = timems;}public ClickProxy(View.OnClickListener origin) {this.origin = origin;}@Overridepublic void onClick(View v) {if (System.currentTimeMillis() - lastclick >= timems) {origin.onClick(v);lastclick = System.currentTimeMillis();} else {if (mIAgain != null) mIAgain.onAgain();}}public interface IAgain {void onAgain();//重复点击}}
使用示例:
btn_click_all_four.setOnClickListener(ClickProxy(View.OnClickListener {Toast.makeText(this@ClickAllActivity, "单击", Toast.LENGTH_SHORT).show()}, ClickProxy.IAgain {Toast.makeText(this@ClickAllActivity, "再次点击", Toast.LENGTH_SHORT).show()}))
三、多次点击
类似于开发者模式多次点击触发,可以自定义点击次数。
object ClickUtils {var counts = 7//点击次数var mhints = LongArray(counts)//记录点击次数var duration = 2000//有效时间fun clickCount(count: Int = 7, sevenAction: () -> Unit, oneAction: () -> Unit) {counts = countSystem.arraycopy(mhints, 1, mhints, 0, mhints.size - 1)mhints[mhints.size - 1] = SystemClock.uptimeMillis()if (mhints[0] >= (SystemClock.uptimeMillis() - duration)) {sevenAction.invoke()//初始化点击次数mhints = LongArray(counts)} else {oneAction.invoke()}}}
参考
Android连续多次点击事件处理
Android 处理 View 重复点击的 4 种方式
ASM 字节码插桩:实现双击防抖
Android一行解决所有双击优化的问题
一行代码解决安卓重复点击
