[更新]:
1.新增OnLazyClickListener
[2019.6.30]
2.triggerLastTime = currentClickTime
挪到if判断内,解决多次快速点击失效bug [2020.10.28]
在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 {
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)
}
用法:
直接新建一个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")
}
扩展:OnLazyClickListener用法
/**************** OnLazyClickListener用法 [Start]********************/
class TestActivity:Activity(), OnLazyClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//Todo: your code
ivBack.setOnClickListener(this)
}
override fun onLazyClick(v: View) {
when(v.id){
R.id.ivBack-> onBackPressed()
}
}
}
/**************** OnLazyClickListener用法 [End]********************/
知识点:
1.利用了kotlin的扩展函数和扩展属性。
2.扩展属性不能额外添加filed。所以我们利用了View的tag属性来保存我们的triggerDelay和triggerLastTime
3.利用了kotlin的默认参数,减少函数重载。