Android empêchant le double-clic sur un bouton

177

Quelle est la meilleure façon d'éviter les doubles clics sur un bouton sous Android?

Androider
la source
3
Voir la solution de qezt seulement elle est entièrement réalisable
Gennadiy Ryabkin
3
La solution de qezt aurait dû être acceptée, de sorte que les personnes qui visitent cette page connaissent l'inconvénient d'utiliser setEnabled (false).
LoveForDroid
Vous pouvez essayer ma bibliothèque, en utilisant la solution au dernier clic: github.com/RexLKW/SClick
Rex Lam
1
@Androider s'il vous plaît changer votre meilleure réponse
Amir133

Réponses:

87

Désactivez le bouton avec setEnabled(false)jusqu'à ce que l'utilisateur puisse le cliquer à nouveau en toute sécurité.

CommonsWare
la source
47
setEnabled (false) ne semble pas fonctionner assez "vite". J'ai mis en place un View.OnClickListener.onClick (vue) pour un bouton. La première chose que je fais dans onClick () est d'écrire une instruction de journal, la deuxième instruction est button.setEnabled (false). Lorsque vous double-cliquez rapidement dans l'émulateur, je vois l'instruction de journal apparaître deux fois! Même lors de l'ajout d'un setClickable (false) juste après cela, l'instruction de journal apparaît deux fois.
QQQuestions
Hmmm, peut-être que le code jusqu'à setEnabled (true) à la fin de onClick () est exécuté si rapidement qu'il est déjà activé à nouveau ...
QQQuestions
91
J'avais un problème similaire. Selon un homme utile, Android met en file d'attente les clics, donc peu importe la vitesse ou la lenteur de l'exécution de votre code onClick (); seulement à quelle vitesse vous cliquez sur le bouton. C'est à dire. Vous avez peut-être déjà désactivé le bouton, mais la file d'attente des clics a déjà été remplie avec deux ou trois clics et la désactivation du bouton n'a aucun effet sur la livraison des clics en file d'attente. (bien que peut-être que cela devrait?)
Nick
3
Ce rare moment où vous voyez «quelqu'un» donne une réponse exacte et non abstraaaaaaaact des réponses à la question posée.: P
Rahul
ce n'est pas toujours la bonne solution. Si votre opération onClick est coûteuse, le bouton ne se désactivera pas assez rapidement. La solution à toute épreuve à mon humble avis consiste à utiliser le dernier temps de clic, mais également à désactiver le bouton pour éviter que l'utilisateur n'appuie à nouveau dessus si vous prévoyez que l'opération durera un certain temps (comme la connexion).
Sarang
368

l'enregistrement d'un dernier clic lors d'un clic évitera ce problème.

c'est à dire

private long mLastClickTime = 0;

...

// inside onCreate or so:

findViewById(R.id.button).setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        // mis-clicking prevention, using threshold of 1000 ms
        if (SystemClock.elapsedRealtime() - mLastClickTime < 1000){
            return;
        }
        mLastClickTime = SystemClock.elapsedRealtime();

        // do your magic here
    }
}
qezt
la source
21
C'est la seule solution qui empêche réellement un double clic. Je viens de passer une heure à essayer toutes les autres car cette méthode est assez maladroite, mais aucune d'entre elles ne pourrait empêcher un double tap rapide sur une vue sauf celle-ci. Google s'il vous plaît résoudre ce problème :)
ashishduh
6
Cette solution fonctionne très bien. Cette solution fonctionne également lorsque vous avez plusieurs boutons à l'écran et que vous souhaitez cliquer sur un seul bouton à la fois.
annulé
12
Cela n'empêche pas complètement les doubles-clics si vous double-cliquez assez rapidement.
Loc
4
Meilleure réponse, elle devrait être au top
Gennadiy Ryabkin
3
Cette solution devrait être la bonne réponse ... setEnabled (false) ne suffit pas.
heloisasim
55

Ma solution est

package com.shuai.view;

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

/**
 * 处理快速在某个控件上双击2次(或多次)会导致onClick被触发2次(或多次)的问题
 * 通过判断2次click事件的时间间隔进行过滤
 * 
 * 子类通过实现{@link #onSingleClick}响应click事件
 */
public abstract class OnSingleClickListener implements View.OnClickListener {
    /**
     * 最短click事件的时间间隔
     */
    private static final long MIN_CLICK_INTERVAL=600;
    /**
     * 上次click的时间
     */
    private long mLastClickTime;

    /**
     * click响应函数
     * @param v The view that was clicked.
     */
    public abstract void onSingleClick(View v);

    @Override
    public final void onClick(View v) {
        long currentClickTime=SystemClock.uptimeMillis();
        long elapsedTime=currentClickTime-mLastClickTime;
        //有可能2次连击,也有可能3连击,保证mLastClickTime记录的总是上次click的时间
        mLastClickTime=currentClickTime;

        if(elapsedTime<=MIN_CLICK_INTERVAL)
            return;

        onSingleClick(v);        
    }

}

L'utilisation est similaire à OnClickListener mais remplace onSingleClick () à la place:

mTextView.setOnClickListener(new OnSingleClickListener() {
            @Override
            public void onSingleClick(View v) {
                if (DEBUG)
                    Log.i("TAG", "onclick!");
            }
     };
jinshiyi11
la source
1
Facile et parfait pour éviter automatiquement les doubles touches.
Benjamin Piette
1
Cela n'empêche pas complètement les doubles-clics si vous double-cliquez assez rapidement.
Loc
1
Excellente solution. Je viens de changer MIN_CLICK_INTERVAL = 1000;
Nizam le
5
Si je devais boutonner avec précision toutes les 0,5 seconde, aucun de mes clics suivants ne passerait car mLastClickTime serait mis à jour à chaque clic. Ma suggestion serait d'attribuer mLastClickTime après avoir vérifié l'intervalle.
k2col
mLastClickTime = currentClickTime; doit être placé après if (elapsedTime <= MIN_CLICK_INTERVAL) return;
Loyea
41

La désactivation du bouton ou la définition d'un clic ne suffit pas si vous effectuez un travail intensif en calcul dans onClick () car les événements de clic peuvent être mis en file d'attente avant que le bouton ne puisse être désactivé. J'ai écrit une classe de base abstraite qui implémente OnClickListener que vous pouvez remplacer à la place, qui résout ce problème en ignorant tous les clics en file d'attente:

/** 
 * This class allows a single click and prevents multiple clicks on
 * the same button in rapid succession. Setting unclickable is not enough
 * because click events may still be queued up.
 * 
 * Override onOneClick() to handle single clicks. Call reset() when you want to
 * accept another click.
 */
public abstract class OnOneOffClickListener implements OnClickListener {
    private boolean clickable = true;

    /**
     * Override onOneClick() instead.
     */
    @Override
    public final void onClick(View v) {
        if (clickable) {
            clickable = false;
            onOneClick(v);
            //reset(); // uncomment this line to reset automatically
        }
    }

    /**
     * Override this function to handle clicks.
     * reset() must be called after each click for this function to be called
     * again.
     * @param v
     */
    public abstract void onOneClick(View v);

    /**
     * Allows another click.
     */
    public void reset() {
        clickable = true;
    }
}

L'utilisation est la même que OnClickListener mais remplace OnOneClick () à la place:

OnOneOffClickListener clickListener = new OnOneOffClickListener() {
    @Override
    public void onOneClick(View v) {

        // Do stuff

        this.reset(); // or you can reset somewhere else with clickListener.reset();
    }
};
myButton.setOnClickListener(clickListener);
Ken
la source
Merci pour le code. Sur la base de ce que vous avez écrit ici, j'ai créé une classe similaire qui empêche les clics si le bouton ou son parent est masqué - c'est drôle qu'Android mettra en file d'attente les clics même si vous masquez le bouton immédiatement après le clic.
nikib3ro
1
J'ai une solution similaire - vous pouvez simplement utiliser cette classe en xml et elle enveloppera les clickListeners pour vous github.com/doridori/AndroidUtilDump/blob/master/android/src/…
Dori
2
C'est une bonne solution, mais onClick () et reset () doivent être synchronisés, sinon un double-clic peut toujours se faufiler.
Tom anMoney
6
@TomanMoney, comment? Tous les événements de clic ne se produisent-ils pas sur un seul thread d'interface utilisateur?
Ken
@Dori le lien est mort
naXa
36

Vous pouvez le faire de manière très sophistiquée avec les fonctions d'extension Kotlin et RxBinding

   fun View.clickWithDebounce(debounceTime: Long = 600L, action: () -> Unit): Disposable =
        RxView.clicks(this)
                .debounce(debounceTime, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe { action() }

ou

fun View.clickWithDebounce(debounceTime: Long = 600L, action: () -> Unit) {
    this.setOnClickListener(object : View.OnClickListener {
        private var lastClickTime: Long = 0

        override fun onClick(v: View) {
            if (SystemClock.elapsedRealtime() - lastClickTime < debounceTime) return
            else action()

            lastClickTime = SystemClock.elapsedRealtime()
        }
    })
}

et puis juste:

View.clickWithDebounce{ Your code }
Yvgen
la source
over engenering
Serg Burlaka
3
Debounce pour Rx ne fonctionnera pas bien ici. Au lieu de cela, "ThrottleFirst" devrait mieux s'adapter. demo.nimius.net/debounce_throttle voici un exemple sur la façon dont ils diffèrent. PS: et en fait, votre implémentation clickWithDebounce est une implémentation d'accélérateur, pas de
debounce
13

J'ai également rencontré un problème similaire, j'affichais des sélecteurs de date et des sélecteurs de temps où parfois il y avait un clic 2 fois. Je l'ai résolu par ceci

long TIME = 1 * 1000;
@Override
public void onClick(final View v) {
v.setEnabled(false);

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

        @Override
        public void run() {
            v.setEnabled(true);
        }
    }, TIME);
}

Vous pouvez changer l'heure en fonction de vos besoins. Cette méthode fonctionne pour moi.

Mudassar
la source
C'est la vraie solution, puisqu'elle réactive automatiquement le bouton une fois le temps écoulé. Les autres solutions bloquent définitivement le bouton si vous cliquez deux fois rapidement. Cette solution résout le problème! Merci
Néstor
10

setEnabled(false) fonctionne parfaitement pour moi.

L'idée est que j'écris { setEnabled(true); }au début et que je le fais juste falseau premier clic du bouton.

saurabh
la source
9

Je sais que c'est une vieille question, mais je partage la meilleure solution que j'ai trouvée pour résoudre ce problème commun

        btnSomeButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // Prevent Two Click
            Utils.preventTwoClick(view);
            // Do magic
        }
    });

Et dans un autre fichier, comme Utils.java

    /**
 * Método para prevenir doble click en un elemento
 * @param view
 */
public static void preventTwoClick(final View view){
    view.setEnabled(false);
    view.postDelayed(new Runnable() {
        public void run() {
           view.setEnabled(true);
        }
    }, 500);
}
Gustavo
la source
8

La solution réelle à ce problème est d'utiliser setEnabled (false) qui grise le bouton et setClickable (false) qui fait en sorte que le deuxième clic ne puisse pas être reçu.J'ai testé cela et cela semble très efficace.

EpicOfChaos
la source
7

Si quelqu'un cherche toujours une réponse courte, vous pouvez utiliser le code ci-dessous

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

Ce code entrera dans le if statementchaque fois que l'utilisateur clique sur le View within 1 second, puis le return;sera lancé et le code supplémentaire ne sera pas lancé.

Rakshit Nawani
la source
2
Cela devrait être la réponse acceptée. Super simple et cela fonctionne même si vous cliquez très vite! Merci pour cela.
Geoffroy CALA
7

La manière idiomatique de K LEANEST Kotlin :

class OnSingleClickListener(private val block: () -> Unit) : View.OnClickListener {

    private var lastClickTime = 0L

    override fun onClick(view: View) {
        if (SystemClock.elapsedRealtime() - lastClickTime < 1000) {
            return
        }
        lastClickTime = SystemClock.elapsedRealtime()

        block()
    }
}

fun View.setOnSingleClickListener(block: () -> Unit) {
    setOnClickListener(OnSingleClickListener(block))
}

Usage:

button.setOnSingleClickListener { ... }
Coureur du vent
la source
6

Ma solution est d'essayer d'utiliser une booleanvariable:

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);
    }
}

Et en utilisant comme ci-dessous:

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   
                }
            }
        });

MISE À JOUR : solution Kotlin, utilisant l'extension de vue

fun View.safeClick(listener: View.OnClickListener, blockInMillis: Long = 500) {
    var lastClickTime: Long = 0
    this.setOnClickListener {
        if (SystemClock.elapsedRealtime() - lastClickTime < blockInMillis) return@setOnClickListener
        lastClickTime = SystemClock.elapsedRealtime()
        listener.onClick(this)
    }
}
GianhTran
la source
5

Click Guard fonctionne bien avec le couteau à beurre

ClickGuard.guard(mPlayButton);
thanhbinh84
la source
4
separete linrary pour la poignée double-cliquez sur le bouton? ha
Serg Burlaka
Puis-je utiliser ce bouton personnalisé à l'intérieur?
Ara Badalyan
@AraBadalyan qu'entendez-vous par «à l'intérieur». Passez simplement votre bouton personnalisé comme paramètre pour la méthode de garde. Ensuite, votre bouton sera protégé du double-clic
thanhbinh84
Je veux dire que je ne veux pas ajouter ClickGuard.guard (mPlayButton) dans toutes les activités qui utilisent onclick. Je veux créer le bouton d'étendue CustomButton et placer ClickGuard dans CustomButton. Mais lorsque j'ajoute ClickGuard dans le constructeur CustomButton, cela ne fonctionnait pas.
Ara Badalyan
@AraBadalyan c'est vrai. Cela ne fonctionne pas de cette façon.
thanhbinh84
5

dans ma situation, j'utilisais une vue de bouton et cela prenait les clics trop rapidement. désactivez simplement le cliquable et réactivez-le après quelques secondes ...

Fondamentalement, j'ai créé une classe wrapper qui entoure vos vues onClickListener. vous pouvez également définir un délai personnalisé si vous le souhaitez.

public class OnClickRateLimitedDecoratedListener implements View.OnClickListener {

    private final static int CLICK_DELAY_DEFAULT = 300;
    private View.OnClickListener onClickListener;
    private int mClickDelay;


        public OnClickRateLimitedDecoratedListener(View.OnClickListener onClickListener) {
            this(onClickListener, CLICK_DELAY_DEFAULT);
        }

        //customize your own delay
        public OnClickRateLimitedDecoratedListener(View.OnClickListener onClickListener, int delay) {
            this.onClickListener = onClickListener;
            mClickDelay = delay;
        }

        @Override
        public void onClick(final View v) {
            v.setClickable(false);
            onClickListener.onClick(v);

            v.postDelayed(new Runnable() {
                @Override
                public void run() {
                    v.setClickable(true);
                }
            }, mClickDelay);
        }
    }

et pour l'appeler, faites simplement ceci:

mMyButton.setOnClickListener(new OnClickRateLimitedDecoratedListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 doSomething();
             }
         }));

ou indiquez votre propre délai:

 mMyButton.setOnClickListener(new OnClickRateLimitedDecoratedListener(new View.OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         doSomething();
                     }
                 },1000));

MISE À JOUR: ci-dessus, un peu à l'ancienne maintenant que RxJava est si répandu. comme d'autres l'ont mentionné, dans Android, nous pourrions utiliser un accélérateur pour ralentir les clics. voici un exemple:

 RxView.clicks(myButton)
                    .throttleFirst(2000, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
                    .subscribe {
                        Log.d("i got delayed clicked")
                    }
        }

vous pouvez utiliser cette bibliothèque pour cela: implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'

j2emanue
la source
4
    button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            //to prevent double click
            button.setOnClickListener(null);
        }
    });
Indrek Kõue
la source
4

Vous pouvez utiliser cette méthode. En utilisant le délai de publication, vous pouvez prendre en charge les événements de double clic.

void debounceEffectForClick (vue vue) {

    view.setClickable(false);

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

        }
    }, 500);
}
manmohan
la source
4

Extension Kotlin qui permet un code en ligne concis et des temps d'attente variables en double clic

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()
        }
    }
}

Usage:

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

Ou

anyView.setNoDoubleClickListener(View.OnClickListener { v ->
    // do stuff
}, 1500)
Jim
la source
Génial, tout le monde devrait l'utiliser, c'est un morceau de code absolument sympa et une excellente raison pour laquelle tout le monde devrait migrer vers kotlin.
Achmad Naufal Syafiq
Cela pourrait être plus agréable si waitMillis est simplement codé en dur, alors les parenthèses extérieures peuvent être supprimées.
WindRider
4

Le code ci-dessous empêchera l'utilisateur de cliquer plusieurs fois en quelques fractions de secondes et ne l'autorisera qu'après 3 secondes.

private long lastClickTime = 0;

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

        lastClickTime = SystemClock.elapsedRealtime();
    }
}
Milan Sheth
la source
3

Il semble que la configuration de vos écouteurs de clic dans onResume et leur annulation dans onPause fasse également l'affaire.

Khendricks
la source
3

Pour moi, je me souviens seulement de l'horodatage et de sa vérification (plus d'une seconde s'est écoulée depuis le clic précédent) a aidé.

shtolik
la source
3

J'espère que cela peut vous aider, mettez le code dans votre gestionnaire d'événements.

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

    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 );
    }
ONG
la source
3

J'ai trouvé qu'aucune de ces suggestions ne fonctionne si la méthode onClick ne revient pas immédiatement. L'événement tactile est mis en file d'attente par Android et le prochain onClick n'est appelé qu'une fois le premier terminé. (Comme cela est fait sur le seul thread d'interface utilisateur, c'est vraiment normal.) J'avais besoin d'utiliser le moment où la fonction onClick est terminée + une variable booléenne pour marquer si le onClick donné est en cours d'exécution. Ces deux attributs de marqueur sont statiques pour éviter que onClickListener ne s'exécute en même temps. (Si l'utilisateur clique sur un autre bouton) Vous pouvez simplement remplacer votre OnClickListener par cette classe et au lieu d'implémenter la méthode onClick, vous devez implémenter la méthode abstraite 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);
}
linczy
la source
3

vous pouvez également utiliser les liaisons rx de jake wharton pour ce faire. voici un échantillon qui se tamponne 2 secondes entre les clics successifs:

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
                });

// note: ignorez l'objet v dans ce cas et je pense toujours.

j2emanue
la source
3

Kotlin crée la classe SafeClickListener

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)
    }
}

créer une fonction dans baseClass ou bien

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

et utilisez sur le bouton clic

btnSubmit.setSafeOnClickListener {
    showSettingsScreen()
}
jai khambhayta
la source
1
La solution la plus propre avec des extensions! Merci!
android_dev
3

À Kotlin

button.setOnClickListener { 
    it?.apply { isEnabled = false; postDelayed({ isEnabled = true }, 400) } //400 ms
    //do your work
}
Владислав Прасков
la source
2

Définir Clickable sur false ne fonctionne pas lors du premier double-clic, mais les doubles-clics suivants sont bloqués. C'est comme si le délégué de clic de chargement la première fois était plus lent et que le second clic était capturé avant la fin du premier.

        Button button = contentView.FindViewById<Button>(Resource.Id.buttonIssue);
        button.Clickable = false;
        IssueSelectedItems();
        button.Clickable = true;
KawBoy
la source
2

Je corrige ce problème en utilisant deux classes, une similaire à la réponse @ jinshiyi11 et la réponse est basée sur un clic explicite, en cela vous ne pouvez cliquer qu'une fois sur un bouton, si vous voulez un autre clic, vous devez l'indiquer explicitement .

/**
 * 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;
    }
}

Exemple d'utilisation:

OnExplicitClickListener clickListener = new OnExplicitClickListener() {
    public void onOneClick(View v) {
        Log.d("example", "explicit click");
        ...
        clickListener.enableClick();    
    }
}
button.setOnClickListener(clickListener);
iberck
la source
2
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");
    }
});
Milan Hlinák
la source
Les écouteurs de vue sont toujours appelés sur un seul thread (main) donc l'utilisation AtomicBooleanne peut pas vraiment aider.
WindRider
2

Essayez ceci, cela fonctionne:

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
    }
});
Roi des messes
la source