Android предотвращает двойной щелчок по кнопке - PullRequest
138 голосов
/ 10 апреля 2011

Каков наилучший способ предотвращения двойного щелчка по кнопке в Android?

Ответы [ 39 ]

3 голосов
/ 22 августа 2018

Мое решение состоит в том, чтобы попытаться использовать boolean переменную:

public class Blocker {
    private static final int DEFAULT_BLOCK_TIME = 1000;
    private boolean mIsBlockClick;

    /**
     * Block any event occurs in 1000 millisecond to prevent spam action
     * @return false if not in block state, otherwise return true.
     */
    public boolean block(int blockInMillis) {
        if (!mIsBlockClick) {
            mIsBlockClick = true;
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    mIsBlockClick = false;
                }
            }, blockInMillis);
            return false;
        }
        return true;
    }

    public boolean block() {
        return block(DEFAULT_BLOCK_TIME);
    }
}

И использовать как показано ниже:

view.setOnClickListener(new View.OnClickListener() {
            private Blocker mBlocker = new Blocker();

            @Override
            public void onClick(View v) {
                if (!mBlocker.block(block-Time-In-Millis)) {
                    // do your action   
                }
            }
        });
3 голосов
/ 08 сентября 2017

Click Guard хорошо работает с ножом для масла

ClickGuard.guard(mPlayButton);
3 голосов
/ 12 июля 2018

Расширение Kotlin, позволяющее получить краткий встроенный код и переменное время ожидания двойного щелчка

fun View.setDoubleClickListener(listener: View.OnClickListener, waitMillis : Long = 1000) {
    var lastClickTime = 0L
    setOnClickListener { view ->
        if (System.currentTimeMillis() > lastClickTime + waitMillis) {
            listener.onClick(view)
            lastClickTime = System.currentTimeMillis()
        }
    }
}

Использование:

anyView.setNoDoubleClickListener(View.OnClickListener { v ->
    // do stuff
})

Или

anyView.setNoDoubleClickListener(View.OnClickListener { v ->
    // do stuff
}, 1500)
2 голосов
/ 25 сентября 2014

Надеюсь, это поможет вам, поместите код в ваш обработчик событий.

// --------------------------------------------------------------------------------

    boolean hasTag = null != which.getTag( R.id.preventing_double_click_tag );

    if ( hasTag ) {
        // Do not handle again...
        return;
    } else {
        which.setTag( R.id.action, Boolean.TRUE );

        which.postDelayed( new Runnable() {
            @Override
            public void run() {
                which.setTag( R.id.action, null );
                Log.d( "onActin", " The preventing double click tag was removed." );
            }

        }, 2000 );
    }
2 голосов
/ 12 мая 2011

Похоже, что установка прослушивателей щелчков в onResume и обнуление их в onPause тоже помогает.

2 голосов
/ 01 марта 2016

Я обнаружил, что ни одно из этих предложений не работает, если метод onClick не возвращается немедленно.Android-событие ставится в очередь, а следующий onClick вызывается только после завершения первого.(Так как это делается в одном потоке пользовательского интерфейса, это действительно нормально.) Мне нужно было использовать время завершения функции onClick + одну логическую переменную, чтобы указать, работает ли данный onClick.Оба эти атрибута маркера являются статическими, чтобы избежать одновременного запуска onClickListener.(Если пользователь нажимает на другую кнопку) Вы можете просто заменить OnClickListener на этот класс, и вместо реализации метода onClick вам нужно реализовать абстрактный метод oneClick ().

    abstract public class OneClickListener implements OnClickListener {

    private static boolean started = false;
    private static long lastClickEndTime = 0;

    /* (non-Javadoc)
     * @see android.view.View.OnClickListener#onClick(android.view.View)
     */
    @Override
    final public void onClick(final View v) {
        if(started || SystemClock.elapsedRealtime()-lastClickEndTime <1000 ){
            Log.d(OneClickListener.class.toString(), "Rejected double click, " + new Date().toString() );
            return; 
        }
        Log.d(OneClickListener.class.toString(), "One click, start: " + new Date().toString() );
        try{
            started = true;
            oneClick(v);
        }finally{
            started = false;
            lastClickEndTime = SystemClock.elapsedRealtime();
            Log.d(OneClickListener.class.toString(), "One click, end: " + new Date().toString() );
        }
    }

    abstract protected void oneClick(View v);
}
2 голосов
/ 26 ноября 2012

Мне помогло только помнить временную метку и проверять ее (что прошло более 1 секунды с момента предыдущего клика).

2 голосов
/ 09 января 2018

Если кто-то все еще ищет короткий ответ, вы можете использовать следующий код

 private static long mLastClickTime = 0;
  if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) { // 1000 = 1second
         return;
    }
 mLastClickTime = SystemClock.elapsedRealtime();

Этот код будет входить в if statement всякий раз, когда пользователь нажимает на View within 1 second, и тогда будет инициироваться return;, а дальнейший код не будет инициироваться.

1 голос
/ 05 октября 2015
    button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            //to prevent double click
            button.setOnClickListener(null);
        }
    });
1 голос
/ 12 апреля 2015

Я исправляю эту проблему, используя два предложения, одно из которых похоже на ответ @ jinshiyi11, а анотер основан на явном щелчке; в этом вы можете нажать кнопку только один раз, если вы хотите еще один щелчок, вы должны указать его явно .

/**
 * Listener que sólo permite hacer click una vez, para poder hacer click
 * posteriormente se necesita indicar explicitamente.
 *
 * @author iberck
 */
public abstract class OnExplicitClickListener implements View.OnClickListener {

    // you can perform a click only once time
    private boolean canClick = true;

    @Override
    public synchronized void onClick(View v) {
        if (canClick) {
            canClick = false;
            onOneClick(v);
        }
    }

    public abstract void onOneClick(View v);

    public synchronized void enableClick() {
        canClick = true;
    }

    public synchronized void disableClick() {
        canClick = false;
    }
}

Пример использования:

OnExplicitClickListener clickListener = new OnExplicitClickListener() {
    public void onOneClick(View v) {
        Log.d("example", "explicit click");
        ...
        clickListener.enableClick();    
    }
}
button.setOnClickListener(clickListener);
...