[Android開發筆記]遮蔽View的重複點選
在開發中我們經常需要這樣的需求,比如一個驗證碼傳送按鈕,我們只想讓它響應500毫秒中的第一次點選事件,該如何處理呢?你可能會說這個簡單,在點選事件中獲取當前時間與上次的比較下,如果小於500毫秒就return掉。是的,這樣可以解決,但是如果現在整個專案的所有按鈕點選事件都需要這樣的需求,該如何處理?不可能內個點選事件中都加入這幾行程式碼吧。
這裡先放上我寫的一個響應第一次點選的工具類,可實現2種模式:
- 第一種:無論點選的哪個View,僅響應第一次點選
- 第二章:同一個View上僅響應第一次點選,不同View間無影響
public class ClickHelper { private static long DELAY = 500L; private static long lastTime = 0L; private static List<Integer> viewIds = null; private static final int SAME_VIEW_SIZE = 10; private ClickHelper() { } public static void setDelay(long delay) { ClickHelper.DELAY = delay; } public static long getDelay() { return DELAY; } public static void onlyFirstIgnoreView(final View target, @NonNull final Callback callback) { long nowTime = System.currentTimeMillis(); if (nowTime - lastTime > DELAY) { callback.onClick(target); lastTime = nowTime; } } public static void onlyFirstSameView(final View target, @NonNull final Callback callback) { long nowTime = System.currentTimeMillis(); int id = target.getId(); if (viewIds == null) { viewIds = new ArrayList<>(SAME_VIEW_SIZE); } if (viewIds.contains(id)) { if (nowTime - lastTime > DELAY) { callback.onClick(target); lastTime = nowTime; } } else { if (viewIds.size() >= SAME_VIEW_SIZE) { viewIds.remove(0); } viewIds.add(id); callback.onClick(target); lastTime = nowTime; } } public interface Callback { void onClick(View view); } }
那如何才能讓它對整個專案的所有點選事件生效呢?我的解決辦法是這樣的。
- 第一步,繼承View.OnClickListener在onClick方法中呼叫工具類回撥到抽象方法,專案中所有的點選事件都去繼承這個抽象類
public abstract class OnFirstClickListener implements View.OnClickListener { @Override public final void onClick(final View v) { ClickHelper.onlyFirstSameView(v, new ClickHelper.Callback() { @Override public void onClick(View view) { onFirstClick(view); } }); } public abstract void onFirstClick(View v); }
-
第二步,在專案的BaseActivity中實現View.OnClickListener介面,在onClick方法中呼叫工具類,回調出遮蔽後的點選事件,子類複寫onClickWithoutLogin或者onClickCheckLogin方法就可以了。至於為什麼會有2個,看名字就知道了,一個驗證了使用者登入狀態,僅在登入狀態響應事件,未登入則跳轉登入介面,多封裝了一層罷了。
/** * 用註解繫結點選事件時,在該方法繫結 */ @Override public void onClick(final View v) { ClickHelper.onlyFirstSameView(v, new ClickHelper.Callback() { @Override public void onClick(View view) { if (!onClickWithoutLogin(view)) { if (UserUtils.doIfLogin(getContext())) { onClickCheckLogin(view); } } } }); } /** * 不需要登入的點選事件 */ public boolean onClickWithoutLogin(View v) { return false; } /** * 必須登入的點選事件 * 如果已經登入直接執行,沒有登入時跳轉登入介面 */ public void onClickCheckLogin(View v) { }
以上只是個人開發中用到的,如果大家有更好的方法,歡迎留言討論。