Avoid Button Multiple Rapid Clicks

Avoid button multiple rapid clicks

Here's a 'debounced' onClick listener that I wrote recently.
You tell it what the minimum acceptable number of milliseconds between clicks is.
Implement your logic in onDebouncedClick instead of onClick

import android.os.SystemClock;
import android.view.View;

import java.util.Map;
import java.util.WeakHashMap;

/**
* A Debounced OnClickListener
* Rejects clicks that are too close together in time.
* This class is safe to use as an OnClickListener for multiple views, and will debounce each one separately.
*/
public abstract class DebouncedOnClickListener implements View.OnClickListener {

private final long minimumIntervalMillis;
private Map<View, Long> lastClickMap;

/**
* Implement this in your subclass instead of onClick
* @param v The view that was clicked
*/
public abstract void onDebouncedClick(View v);

/**
* The one and only constructor
* @param minimumIntervalMillis The minimum allowed time between clicks - any click sooner than this after a previous click will be rejected
*/
public DebouncedOnClickListener(long minimumIntervalMillis) {
this.minimumIntervalMillis = minimumIntervalMillis;
this.lastClickMap = new WeakHashMap<>();
}

@Override
public void onClick(View clickedView) {
Long previousClickTimestamp = lastClickMap.get(clickedView);
long currentTimestamp = SystemClock.uptimeMillis();

lastClickMap.put(clickedView, currentTimestamp);
if(previousClickTimestamp == null || Math.abs(currentTimestamp - previousClickTimestamp) > minimumIntervalMillis) {
onDebouncedClick(clickedView);
}
}
}

Android Preventing Double Click On A Button

Disable the button with setEnabled(false) until it is safe for the user to click it again.

How to avoid multiple button click at same time in android?

The standard way to avoid multiple clicks is to save the last clicked time and avoid the other button clicks within 1 second (or any time span).
Example:

// Make your activity class to implement View.OnClickListener
public class MenuPricipalScreen extends Activity implements View.OnClickListener{

@Override
protected void onCreate(Bundle savedInstanceState) {
// setup listeners.
findViewById(R.id.imageView2).setOnClickListener(MenuPricipalScreen.this);
findViewById(R.id.imageView3).setOnClickListener(MenuPricipalScreen.this);
...
}

.
.
.

// variable to track event time
private long mLastClickTime = 0;

// View.OnClickListener.onClick method defination

@Override
public void onClick(View v) {
// Preventing multiple clicks, using threshold of 1 second
if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) {
return;
}
mLastClickTime = SystemClock.elapsedRealtime();

// Handle button clicks
if (v == R.id.imageView2) {
// Do your stuff.
} else if (v == R.id.imageView3) {
// Do your stuff.
}
...
}

.
.
.

}

How to disable a button for multiple click?

I have made public method for avoid double clicking issue on view.

Please check this method,

/***
* To prevent from double clicking the row item and so prevents overlapping fragment.
* **/
public static void avoidDoubleClicks(final View view) {
final long DELAY_IN_MS = 900;
if (!view.isClickable()) {
return;
}
view.setClickable(false);
view.postDelayed(new Runnable() {
@Override
public void run() {
view.setClickable(true);
}
}, DELAY_IN_MS);
}

You can use the method by following way,

  buttonTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(String clickedText) {
Utils.avoidDoubleClicks(alertViewHolder.tv_alert);

// Rest code here for onlick listener

});

Or another way is,

private long lastClickTime = 0;

View.OnClickListener buttonHandler = new View.OnClickListener() {
public void onClick(View v) {
// preventing double, using threshold of 1000 ms
if (SystemClock.elapsedRealtime() - lastClickTime < 1000){
return;
}

lastClickTime = SystemClock.elapsedRealtime();
}
}

Prevent or avoid Multiple clicks in Android app (Kotlin Language)

Solving Android multiple clicks problem — Kotlin

I searched the community and found amazing solution like creating a custom click listener that will preserve the last click time and prevent clicking for a specific period
But — as a big fan of Kotlin — I was thinking to have something to use very smoothly using the power of lambdas and closures.
So I came up with this implementation, hope to help you

Step 1 : Create class with name SafeClickListener.kt

class SafeClickListener(

private var defaultInterval: Int = 1000,
private val onSafeCLick: (View) -> Unit
) : View.OnClickListener {
private var lastTimeClicked: Long = 0
override fun onClick(v: View) {
if (SystemClock.elapsedRealtime() - lastTimeClicked < defaultInterval) {
return
}
lastTimeClicked = SystemClock.elapsedRealtime()
onSafeCLick(v)
}
}

Step 2 : Add extension function to make it works with any view, this will create a new SafeClickListener and delegate the work to it.

    fun View.setSafeOnClickListener(onSafeClick: (View) -> Unit) {
val safeClickListener = SafeClickListener {
onSafeClick(it)
}
setOnClickListener(safeClickListener)
}

Step 3 : Now it is very easy to use it. Just replace button1.setonclicklistner with setSafeOnClickListener.

settingsButton.setSafeOnClickListener {
showSettingsScreen()
}

Preventing rapid clicks on a button and making a request using rxjava

Thanks for all the answers.

However, I found a solution that works using RxBinding with debounce operator. I'm posting here as it could be useful to someone else.

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PokemonViewHolder {
binding = PokemonListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
val pokemonViewHolder = PokemonViewHolder(binding.root)

pokemonViewHolder.itemView.clicks()
.debounce(300, TimeUnit.MILLISECONDS)
.subscribeBy(
onNext = {
val name = pokemonList[pokemonViewHolder.adapterPosition].name

if(::pokemonTapped.isInitialized) {
pokemonTapped(name)
}
},
onError = { Timber.e(it, "Failed to send pokemon request %s", it.localizedMessage) }
).addTo(compositeDisposable)

return pokemonViewHolder
}

How to prevent rapid double click on a button

I am doing like this it works very well.

public abstract class OnOneOffClickListener implements View.OnClickListener {

private static final long MIN_CLICK_INTERVAL=600;

private long mLastClickTime;

public static boolean isViewClicked = false;

public abstract void onSingleClick(View v);

@Override
public final void onClick(View v) {
long currentClickTime=SystemClock.uptimeMillis();
long elapsedTime=currentClickTime-mLastClickTime;

mLastClickTime=currentClickTime;

if(elapsedTime<=MIN_CLICK_INTERVAL)
return;
if(!isViewClicked){
isViewClicked = true;
startTimer();
} else {
return;
}
onSingleClick(v);
}
/**
* This method delays simultaneous touch events of multiple views.
*/
private void startTimer() {
Handler handler = new Handler();

handler.postDelayed(new Runnable() {

@Override
public void run() {
isViewClicked = false;
}
}, 600);

}

}

How to prevent repeating actions on double click on the button?

This is actually a surprisingly complex problem. The root of the issue is that UI events (e.g. a button click) cause messages to be "posted" to the end of a message queue. If you are fast enough, it's possible to get many of these messages posted to the message queue before the first one is ever processed.

This means that even disabling the button inside your onClick() method won't truly solve the problem (since the disabling won't "happen" until the first message is processed, but you might already have three other duplicate messages waiting in the message queue).

The best thing to do is to track some sort of boolean flag and check the flag every time inside onClick():

private boolean firstClick = true;
button.setOnClickListener(v -> {
if (firstClick) {
firstClick = false;
// do your stuff
}
});

You have to remember to reset firstClick back to true whenever you want to re-enable button taps, of course.



Related Topics



Leave a reply



Submit