一、双击监听
既可以监听单击,又可以监听双击。
**
* 点击加双击监听
*/
public abstract class DoubleClickListener implements View.OnClickListener {
long mLastTime;
@Override
public 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() {
@Override
public 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 = delay
return 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 = time
setOnClickListener {
if (clickEnable()) {
block(it as T)
}
}
}
private var <T : View> T.triggerLastTime: Long
get() = if (getTag(1123460103) != null) getTag(1123460103) as Long else -601
set(value) {
setTag(1123460103, value)
}
private var <T : View> T.triggerDelay: Long
get() = if (getTag(1123461123) != null) getTag(1123461123) as Long else 600
set(value) {
setTag(1123461123, value)
}
private fun <T : View> T.clickEnable(): Boolean {
var flag = false
val currentClickTime = System.currentTimeMillis()
if (currentClickTime - triggerLastTime >= triggerDelay) {
flag = true
triggerLastTime = 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;
}
@Override
public 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; // 两次点击间隔不能少于1000ms
private 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; //ms
private 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;
}
@Override
public 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 = count
System.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一行解决所有双击优化的问题
一行代码解决安卓重复点击