安卓按鈕防抖動(dòng)之終極解決方案

開(kāi)發(fā)過(guò)程中,我們經(jīng)常會(huì)用到OnClick點(diǎn)擊事件,常用的寫(xiě)法可能是這樣的:

btn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //TODO
            }
        });

或者是這樣的:

btn.setOnClickListener(this);

@Override
public void onClick(View v) {
   //TODO
}

正常情況下,這樣的代碼是沒(méi)有什么問(wèn)題的,但是大家都知道安卓碎片化嚴(yán)重,每個(gè)手機(jī)的性能也千差萬(wàn)別。想必大家都遇到過(guò),在比較卡的手機(jī)上,快速點(diǎn)擊按鈕打開(kāi)一個(gè)頁(yè)面,結(jié)果發(fā)現(xiàn)這個(gè)頁(yè)面被打開(kāi)了兩次...

一般這種情況下,我們會(huì)打開(kāi)百度,看看萬(wàn)能的網(wǎng)友都是怎么處理這種問(wèn)題的(當(dāng)時(shí)我就是這么做的??),搜索到的處理方式可能是這樣的:

btn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //TODO
                btn.setClickable(false);
                btn.setEnabled(false);
            }
        });

也可能是這樣的:

public abstract class NoDoubleClickListener implements OnClickListener {

    public static final int MIN_CLICK_DELAY_TIME = 1000;
    private long lastClickTime = 0;

    @Override
    public void onClick(View v) {
        long currentTime = Calendar.getInstance().getTimeInMillis();
        if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME{
            lastClickTime = currentTime;
            onNoDoubleClick(v);
        } 
     }  
 
    public abstract void onNoDoubleClick(View v);
}

btn.setOnClickListener(new NoDoubleClickListener() {
            @Override
            public void onNoDoubleClick(View v) {
                 //TODO
            }
        }); 

還有的說(shuō)用RxBinding,由于涉及到Rxjava相關(guān)的知識(shí),篇幅原因,我這里就不過(guò)多描述,感興趣的同學(xué)可以自行百度了解。

當(dāng)然,上述幾種方式均能達(dá)到防止按鈕快速點(diǎn)擊,但是其弊端也比較明顯。先說(shuō)第一種方式,這種方法雖然可以防止快速點(diǎn)擊,但是其給體驗(yàn)上的影響還是非常大的,想想如果你這個(gè)按鈕點(diǎn)擊后會(huì)有網(wǎng)絡(luò)請(qǐng)求,如果網(wǎng)絡(luò)請(qǐng)求執(zhí)行過(guò)程比較長(zhǎng)的話(huà),按鈕一直無(wú)法被點(diǎn)擊,會(huì)讓用戶(hù)以為出現(xiàn)了bug;方式二相比第一種方法,體驗(yàn)上倒是沒(méi)什么問(wèn)題,但是其弊端在于只能通過(guò)匿名內(nèi)部類(lèi)的方式注冊(cè)點(diǎn)擊事件,當(dāng)出現(xiàn)一個(gè)界面按鈕比較多,寫(xiě)起來(lái)代碼就顯得比較臃腫了。

說(shuō)了這么多,是時(shí)候展示真正的技術(shù)了,不多BB,直接上代碼。

首先我們定義一個(gè)點(diǎn)擊事件接口

public interface OnLimitClickListener {

    /**
     * 按鈕點(diǎn)擊事件
     * @param view
     */
    void onClick(View view);

}

再定義一個(gè)抽象類(lèi)對(duì)我們的點(diǎn)擊事件做一層包裝

public class OnLimitClickHelper implements View.OnClickListener {
    public static final int LIMIT_TIME = 300;
    private long lastClickTime = 0;
    private OnLimitClickListener onLimitClickListener = null;

    public OnLimitClickHelper(OnLimitClickListener onLimitClickListener){
        this.onLimitClickListener = onLimitClickListener;
    }

    @Override
    public void onClick(View v) {
        long curTime = Calendar.getInstance().getTimeInMillis();
        if (curTime - lastClickTime > LIMIT_TIME) {
            lastClickTime = curTime;
            if(onLimitClickListener != null){
                onLimitClickListener.onClick(v);
            }
        }
    }
}

ok,完工!??????

最后我們看看Activity的使用:

public abstract class MainActivity extends AppCompatActivity implements OnLimitClickListener {
    private Button btn = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn = findViewById(R.id.btn);
        btn.setOnClickListener(new OnLimitClickHelper(this));
    }

    @Override
    public void onClick(View v) {
        //TODO
    }
}

覺(jué)得寫(xiě)的不錯(cuò)的朋友,幫忙點(diǎn)下喜歡,你們的支持是我創(chuàng)作的動(dòng)力!大家有什么問(wèn)題也可以在下方評(píng)論,有時(shí)間我會(huì)一一解答,感謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,160評(píng)論 25 708
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線(xiàn)程,因...
    小菜c閱讀 7,358評(píng)論 0 17
  • 文章轉(zhuǎn)自:http://gank.io/post/560e15be2dca930e00da1083作者:扔物線(xiàn)在正...
    xpengb閱讀 7,140評(píng)論 9 73
  • 本次課作業(yè)內(nèi)容為: 選擇自己的簡(jiǎn)書(shū)作業(yè)網(wǎng)址為目標(biāo)分析頁(yè)面 提交頁(yè)面結(jié)構(gòu)分析 提交元素標(biāo)簽位置信息 課業(yè)工具:chr...
    Bog5d閱讀 401評(píng)論 0 1
  • 我的童年是在會(huì)寧南端的大山深處度過(guò)的,那里有我的故鄉(xiāng),有我的桑杏、玲檎、七月黃、艷果紅和化心果,有我的地窩窩、麻雀...
    瑋山閱讀 1,570評(píng)論 4 1

友情鏈接更多精彩內(nèi)容