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

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

Ответы [ 39 ]

1 голос
/ 06 ноября 2016
final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {

    private final AtomicBoolean onClickEnabled = new AtomicBoolean(true);

    @Override
    public void onClick(View v) {
        Log.i("TAG", "onClick begin");
        if (!onClickEnabled.compareAndSet(true, false)) {
            Log.i("TAG", "onClick not enabled");
            return;
        }

        button.setEnabled(false);

        // your action here

        button.setEnabled(true);
        onClickEnabled.set(true);
        Log.i("TAG", "onClick end");
    }
});
1 голос
/ 15 мая 2018

Мы могли бы использовать только что синхронизированную кнопку:

@Override
public void onClick(final View view) {
    synchronized (view) {

        view.setEnabled(false);

        switch (view.getId()) {
            case R.id.id1:
                ...
                break;
            case R.id.id2:
                ...
                break;
                ...
        }

        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                view.setEnabled(true);
            }
        }, 1000);
    }
}

Удачи)

1 голос
/ 28 марта 2012

Установка Clickable на false не работает при первом двойном щелчке, но последующие двойные щелчки блокируются. Как будто делегат щелчка загрузки в первый раз медленнее, а второй щелчок захватывается до завершения первого.

        Button button = contentView.FindViewById<Button>(Resource.Id.buttonIssue);
        button.Clickable = false;
        IssueSelectedItems();
        button.Clickable = true;
1 голос
/ 14 декабря 2016

Попробуйте, это работает:

mButton.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {

                mSlotLayout.setEnabled(false);

        //      do your work here

                Timer buttonTimer = new Timer();
                buttonTimer.schedule(new TimerTask() {

                    @Override
                    public void run() {

                        runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                mButton.setEnabled(true);
                            }
                        });
                    }
                }, 500); // delay button enable for 0.5 sec
    }
});
1 голос
/ 16 января 2018

Вы можете использовать этот метод.Используя пост-задержку, вы можете позаботиться о событиях двойного щелчка.

void debounceEffectForClick (View view) {

    view.setClickable(false);

    view.postDelayed(new Runnable() {
        @Override
        public void run() {
            view.setClickable(true);

        }
    }, 500);
}
1 голос
/ 12 августа 2017

Вы также можете использовать rx-привязки Джейка Уортона для достижения этой цели.Вот пример, который добавляет 2 секунды между последовательными щелчками:

RxView.clicks(btnSave)
                .throttleFirst(2000, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Object>() {
                    @Override
                    public void accept( Object v) throws Exception {
//handle onclick event here
                });

// примечание: игнорируйте Object v в этом случае, и я думаю всегда

0 голосов
/ 04 мая 2018
The Best and simple solution i found is 
1. to create a boolean and set as false (default) like
private boolean itemClicked = false;

/* for a safer side you can also declare boolean false in onCreate() also. */
and at onclick() method check 
2. if(!itemClicked)
{
itemClicked = true;
// rest of your coding functionality goes here of onClick method.
}
3. last step is to set boolean false in onResume()
@override
onResume()
{
super.onResume(0);
itemClicked = false;
}
0 голосов
/ 01 мая 2015

Я предпочитаю использовать семафорный блок. Он поточно-ориентирован и может использоваться не только для кнопок.

Пример кода прост:

private UtilsSemaphore buttonSemaphore = new UtilsSemaphore();

public void onClick(View view)
{

    boolean isAllowed = buttonSemaphore.lock();

    if(!isAllowed)
    {
        return;
    }

    final View clickedButton = view;

    clickedButton.setEnabled(false);

    /* some code */

    buttonSemaphore.unlock();
    clickedButton.setEnabled(true);
}


public class UtilsSemaphore {

    public int counter = 0;

    public boolean lock()
    {
        int counterValue = ++counter;
        boolean isAllowed = counterValue < 2;

        if(!isAllowed)
        {
            unlock();
        }

        return isAllowed;
    }

    public void unlock()
    {
        --counter;
    }

}
0 голосов
/ 06 мая 2015

Если единственное, что делает кнопка, это запускает новое действие, то проблему можно решить с помощью режима активации " singleTop " и FLAG_ACTIVITY_CLEAR_TOP , установленного в намерении.Это не будет работать в случае сложной иерархии действий, но подходит для простой древовидной структуры приложения.

0 голосов
/ 31 мая 2019

для любого, кто использует привязку данных:

@BindingAdapter("onClickWithDebounce")
fun onClickWithDebounce(view: View, listener: android.view.View.OnClickListener) {
    view.setClickWithDebounce {
        listener.onClick(view)
    }
}

object LastClickTimeSingleton {
    var lastClickTime: Long = 0
}

fun View.setClickWithDebounce(action: () -> Unit) {
    setOnClickListener(object : View.OnClickListener {

        override fun onClick(v: View) {
            if (SystemClock.elapsedRealtime() - LastClickTimeSingleton.lastClickTime < 500L) return
            else action()
            LastClickTimeSingleton.lastClickTime = SystemClock.elapsedRealtime()
        }
    })
}



<androidx.appcompat.widget.AppCompatButton
                    ..
  android:text="@string/signup_signin"
  app:onClickWithDebounce="@{() -> viewModel.onSignUpClicked()}"
                   ... />
...