[Kotlin]利用擴展函數(shù)優(yōu)雅的實現(xiàn)“防止重復(fù)點擊”

[更新]:
1.新增OnLazyClickListener [2019.6.30]
2.triggerLastTime = currentClickTime挪到if判斷內(nèi),解決多次快速點擊失效bug [2020.10.28]

在Android的代碼實現(xiàn)中羽圃,我們不可避免的會經(jīng)常跟點擊事件setOnClickListener打交道持舆。
重復(fù)點擊又是我們不得不面對的問題甸怕。

Java實現(xiàn)

如果用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實現(xiàn)

如果Rxjava宪塔,我們可以很方便的利用第三方庫Rxbinding的Rxview.clicks處理

  RxView.clicks(view)
                .throttleFirst(1, TimeUnit.SECONDS)
                .subscribe {
                ...
                }

Kotlin擴展實現(xiàn)

當(dāng)我們切換到kotlin,便可以利用它的擴展函數(shù)和擴展屬性來打造我們的點擊事件囊拜。
具體代碼如下:

/***
 * 設(shè)置延遲時間的View擴展
 * @param delay Long 延遲時間某筐,默認(rèn)600毫秒
 * @return T
 */
fun <T : View> T.withTrigger(delay: Long = 600): T {
    triggerDelay = delay
    return this
}

/***
 * 點擊事件的View擴展
 * @param block: (T) -> Unit 函數(shù)
 * @return Unit
 */
fun <T : View> T.click(block: (T) -> Unit) = setOnClickListener {
    block(it as T)
}

/***
 * 帶延遲過濾的點擊事件View擴展
 * @param delay Long 延遲時間,默認(rèn)600毫秒
 * @param block: (T) -> Unit 函數(shù)
 * @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
}

/***
 * 帶延遲過濾的點擊事件監(jiān)聽冠跷,見[View.OnClickListener]
 * 延遲時間根據(jù)triggerDelay獲饶咸堋:600毫秒,不能動態(tài)設(shè)置
 */
interface OnLazyClickListener : View.OnClickListener {

    override fun onClick(v: View?) {
        if (v?.clickEnable() == true) {
            onLazyClick(v)
        }
    }

    fun onLazyClick(v: View)
}
用法:

直接新建一個kt文件蜜托,將上述代碼直接復(fù)制進(jìn)去抄囚,便可如下使用:

        //不帶過濾的普通點擊
        view.click {
            L.e("aaron click test")
        }
        //帶默認(rèn)600毫秒過濾的點擊事件(方法1)
        view.clickWithTrigger {
            L.e("aaron clickWithTrigger test")
        }
        //帶默認(rèn)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的擴展函數(shù)和擴展屬性。
2.擴展屬性不能額外添加filed橄务。所以我們利用了View的tag屬性來保存我們的triggerDelay和triggerLastTime
3.利用了kotlin的默認(rèn)參數(shù)幔托,減少函數(shù)重載。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仪糖,一起剝皮案震驚了整個濱河市柑司,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌锅劝,老刑警劉巖攒驰,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異故爵,居然都是意外死亡玻粪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門诬垂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來劲室,“玉大人,你說我怎么就攤上這事结窘『苎螅” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵隧枫,是天一觀的道長喉磁。 經(jīng)常有香客問我谓苟,道長,這世上最難降的妖魔是什么协怒? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任涝焙,我火速辦了婚禮,結(jié)果婚禮上孕暇,老公的妹妹穿的比我還像新娘仑撞。我一直安慰自己,他們只是感情好妖滔,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布隧哮。 她就那樣靜靜地躺著,像睡著了一般铛楣。 火紅的嫁衣襯著肌膚如雪近迁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天簸州,我揣著相機與錄音鉴竭,去河邊找鬼。 笑死岸浑,一個胖子當(dāng)著我的面吹牛搏存,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播矢洲,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼璧眠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了读虏?” 一聲冷哼從身側(cè)響起责静,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盖桥,沒想到半個月后灾螃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡揩徊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年腰鬼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片塑荒。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡熄赡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出齿税,到底是詐尸還是另有隱情彼硫,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站乌助,受9級特大地震影響溜在,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜他托,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仆葡。 院中可真熱鬧赏参,春花似錦、人聲如沸沿盅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腰涧。三九已至韧掩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窖铡,已是汗流浹背疗锐。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留费彼,地道東北人滑臊。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像箍铲,于是被迫代替她去往敵國和親雇卷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容