一、双击监听

既可以监听单击,又可以监听双击。

  1. **
  2. * 点击加双击监听
  3. */
  4. public abstract class DoubleClickListener implements View.OnClickListener {
  5. long mLastTime;
  6. @Override
  7. public void onClick(final View view) {
  8. long nowTime = System.currentTimeMillis();
  9. view.removeCallbacks(runnable);
  10. //第一次点击,存下时间,等待下次点击
  11. if ((nowTime - mLastTime) < 350) {//双击
  12. doubleListener(view);
  13. } else {
  14. view.postDelayed(runnable, 350);
  15. }
  16. mLastTime = nowTime;
  17. }
  18. Runnable runnable = new Runnable() {
  19. @Override
  20. public void run() {
  21. singleListener();
  22. }
  23. };
  24. protected abstract void singleListener();
  25. protected abstract void doubleListener(View view);
  26. }

二、重复点击处理

2.1 kotlin 扩展函数处理

  1. ***https://www.jianshu.com/p/7118226ecba9
  2. * 设置延迟时间的View扩展
  3. * @param delay Long 延迟时间,默认600毫秒
  4. * @return T
  5. */
  6. fun <T : View> T.withTrigger(delay: Long = 600): T {
  7. triggerDelay = delay
  8. return this
  9. }
  10. /***
  11. * 点击事件的View扩展
  12. * @param block: (T) -> Unit 函数
  13. * @return Unit
  14. */
  15. fun <T : View> T.click(block: (T) -> Unit) = setOnClickListener {
  16. block(it as T)
  17. }
  18. /***
  19. * 带延迟过滤的点击事件View扩展
  20. * @param delay Long 延迟时间,默认600毫秒
  21. * @param block: (T) -> Unit 函数
  22. * @return Unit
  23. */
  24. fun <T : View> T.clickWithTrigger(time: Long = 600, block: (T) -> Unit){
  25. triggerDelay = time
  26. setOnClickListener {
  27. if (clickEnable()) {
  28. block(it as T)
  29. }
  30. }
  31. }
  32. private var <T : View> T.triggerLastTime: Long
  33. get() = if (getTag(1123460103) != null) getTag(1123460103) as Long else -601
  34. set(value) {
  35. setTag(1123460103, value)
  36. }
  37. private var <T : View> T.triggerDelay: Long
  38. get() = if (getTag(1123461123) != null) getTag(1123461123) as Long else 600
  39. set(value) {
  40. setTag(1123461123, value)
  41. }
  42. private fun <T : View> T.clickEnable(): Boolean {
  43. var flag = false
  44. val currentClickTime = System.currentTimeMillis()
  45. if (currentClickTime - triggerLastTime >= triggerDelay) {
  46. flag = true
  47. triggerLastTime = currentClickTime
  48. }
  49. return flag
  50. }
  51. /***
  52. * 带延迟过滤的点击事件监听,见[View.OnClickListener]
  53. * 延迟时间根据triggerDelay获取:600毫秒,不能动态设置
  54. */
  55. interface OnLazyClickListener : View.OnClickListener {
  56. override fun onClick(v: View?) {
  57. if (v?.clickEnable() == true) {
  58. onLazyClick(v)
  59. }
  60. }
  61. fun onLazyClick(v: View)
  62. }

使用示例:

  1. btn_click_all_one.clickWithTrigger {
  2. Toast.makeText(this, "hai", Toast.LENGTH_SHORT).show()
  3. }
  4. btn_click_all_two.withTrigger().click {
  5. Toast.makeText(this, "hello", Toast.LENGTH_SHORT).show()
  6. }

2.2 java 处理

2.2.1 自定义抽象函数,可以同时监听单击和重复点击

  1. /**
  2. * @author : Lss Administrator
  3. * @FileName: CustomClickListener
  4. * @e-mail : kiwilss@163.com
  5. * @time : 2020/12/17
  6. * @desc : {https://segmentfault.com/a/1190000016442998}
  7. */
  8. public abstract class CustomClickListener implements View.OnClickListener {
  9. private long mLastTime;
  10. private long mTimeInterval = 1000L;
  11. public CustomClickListener() {
  12. }
  13. public CustomClickListener(long mTimeInterval) {
  14. this.mTimeInterval = mTimeInterval;
  15. }
  16. @Override
  17. public void onClick(View view) {
  18. long nowTime = System.currentTimeMillis();
  19. if (nowTime - mLastTime > mTimeInterval) {
  20. //单次点击
  21. onSingleClick(view);
  22. mLastTime = nowTime;
  23. } else {
  24. //快速点击
  25. onFastClick(view);
  26. }
  27. }
  28. protected abstract void onSingleClick(View view);
  29. protected void onFastClick(View view) {
  30. }
  31. }

使用示例:

  1. btn_click_all_three.setOnClickListener(object : CustomClickListener() {
  2. override fun onSingleClick(view: View?) {
  3. Toast.makeText(this@ClickAllActivity, "单击", Toast.LENGTH_SHORT).show()
  4. }
  5. override fun onFastClick(view: View?) {
  6. super.onFastClick(view)
  7. Toast.makeText(this@ClickAllActivity, "快速点击", Toast.LENGTH_SHORT).show()
  8. }
  9. })

2.2.2 工具类判断

有局限,对多个控件使用时,相当于一个控件。

  1. /**
  2. * @author : Lss Administrator
  3. * @FileName: ClickUtils
  4. * @e-mail : kiwilss@163.com
  5. * @time : 2020/12/17
  6. * @desc : {点击限制,只能对一个控件使用,多个控件使用时会在1s内都无法点击}
  7. */
  8. public class ClickUtils {
  9. private static final int MIN_DELAY_TIME = 1000; // 两次点击间隔不能少于1000ms
  10. private static long lastClickTime;
  11. public static boolean clickEnable() {
  12. boolean flag = false;
  13. long currentClickTime = System.currentTimeMillis();
  14. if ((currentClickTime - lastClickTime) >= MIN_DELAY_TIME) {
  15. flag = true;
  16. }
  17. lastClickTime = currentClickTime;
  18. return flag;
  19. }
  20. }

对多个控件单独设置:

  1. public final class XClickUtil {
  2. /**
  3. * 最近一次点击的时间
  4. */
  5. private static long mLastClickTime;
  6. /**
  7. * 最近一次点击的控件ID
  8. */
  9. private static int mLastClickViewId;
  10. /**
  11. * 是否是快速点击
  12. *
  13. * @param v 点击的控件
  14. * @param intervalMillis 时间间期(毫秒)
  15. * @return true:是,false:不是
  16. */
  17. public static boolean isFastDoubleClick(View v, long intervalMillis) {
  18. int viewId = v.getId();
  19. long time = System.currentTimeMillis();
  20. long timeInterval = Math.abs(time - mLastClickTime);
  21. if (timeInterval < intervalMillis && viewId == mLastClickViewId) {
  22. return true;
  23. } else {
  24. mLastClickTime = time;
  25. mLastClickViewId = viewId;
  26. return false;
  27. }
  28. }
  29. }

2.2.3 使用代理

  1. /**
  2. * 代理模式
  3. * https://www.jianshu.com/p/dadebb8c3a0e
  4. */
  5. public class ClickProxy implements View.OnClickListener {
  6. private View.OnClickListener origin;
  7. private long lastclick = 0;
  8. private long timems = 1000; //ms
  9. private IAgain mIAgain;
  10. public ClickProxy(View.OnClickListener origin, IAgain again) {
  11. this.origin = origin;
  12. this.mIAgain = again;
  13. }
  14. public ClickProxy(View.OnClickListener origin, long timems, IAgain again) {
  15. this.origin = origin;
  16. this.mIAgain = again;
  17. this.timems = timems;
  18. }
  19. public ClickProxy(View.OnClickListener origin) {
  20. this.origin = origin;
  21. }
  22. @Override
  23. public void onClick(View v) {
  24. if (System.currentTimeMillis() - lastclick >= timems) {
  25. origin.onClick(v);
  26. lastclick = System.currentTimeMillis();
  27. } else {
  28. if (mIAgain != null) mIAgain.onAgain();
  29. }
  30. }
  31. public interface IAgain {
  32. void onAgain();//重复点击
  33. }
  34. }

使用示例:

  1. btn_click_all_four.setOnClickListener(ClickProxy(View.OnClickListener {
  2. Toast.makeText(this@ClickAllActivity, "单击", Toast.LENGTH_SHORT).show()
  3. }, ClickProxy.IAgain {
  4. Toast.makeText(this@ClickAllActivity, "再次点击", Toast.LENGTH_SHORT).show()
  5. }))

三、多次点击

类似于开发者模式多次点击触发,可以自定义点击次数。

  1. object ClickUtils {
  2. var counts = 7//点击次数
  3. var mhints = LongArray(counts)//记录点击次数
  4. var duration = 2000//有效时间
  5. fun clickCount(count: Int = 7, sevenAction: () -> Unit, oneAction: () -> Unit) {
  6. counts = count
  7. System.arraycopy(mhints, 1, mhints, 0, mhints.size - 1)
  8. mhints[mhints.size - 1] = SystemClock.uptimeMillis()
  9. if (mhints[0] >= (SystemClock.uptimeMillis() - duration)) {
  10. sevenAction.invoke()
  11. //初始化点击次数
  12. mhints = LongArray(counts)
  13. } else {
  14. oneAction.invoke()
  15. }
  16. }
  17. }

参考

Android连续多次点击事件处理
Android 处理 View 重复点击的 4 种方式
ASM 字节码插桩:实现双击防抖
Android一行解决所有双击优化的问题
一行代码解决安卓重复点击