在Android的代码实现中,我们不可避免的会经常跟点击事件setOnClickListener打交道。
而重复点击又是我们不得不面对的问题。
Java实现
如果用java,我们可以写一个工具类处理,比如:
public class Utils {
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;
}
}
Rxjava实现
如果Rxjava,我们可以很方便的利用第三方库Rxbinding的Rxview.clicks处理
RxView.clicks(view)
.throttleFirst(1, TimeUnit.SECONDS)
.subscribe {
...
}
Kotlin扩展实现
当我们切换到kotlin,便可以利用它的扩展函数和扩展属性来打造我们的点击事件。
具体代码如下:
/***
* 设置延迟时间的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 {
if (clickEnable()) {
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 0
set(value) {
setTag(1123460103, value)
}
private var <T : View> T.triggerDelay: Long
get() = if (getTag(1123461123) != null) getTag(1123461123) as Long else -1
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
}
用法:
直接新建一个kt文件,将上述代码直接复制进去,便可如下使用:
//不带过滤的普通点击
view.click {
L.e("aaron click test")
}
//带默认600毫秒过滤的点击事件(方法1)
view.clickWithTrigger {
L.e("aaron clickWithTrigger test")
}
//带默认600毫秒过滤的点击事件(方法2)
view.withTrigger().click {
L.e("aaron click test")
}
//带700毫秒过滤的点击事件(方法1)
bind.clickWithTrigger(700) {
L.e("aaron clickWithTrigger test")
}
//带700毫秒过滤的点击事件(方法2)
view.withTrigger(700).click {
L.e("aaron click test")
}
知识点:
1.利用了kotlin的扩展函数和扩展属性。
2.扩展属性不能额外添加filed。所以我们利用了View的tag属性来保存我们的triggerDelay和triggerLastTime
3.利用了kotlin的默认参数,减少函数重载。
网友评论
我的需求是:点击后1s内如果没有返回,开启进度条,5s后还没有返回,请求超时取消进度条。