web-dev-qa-db-fra.com

Android Preventing Double Click On A Button

Quel est le meilleur moyen d'éviter les doubles clics sur un bouton sous Android? 

115
Androider

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

63
CommonsWare

enregistrer un dernier clic en cliquant permettra d'éviter 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
    }
}
271
qezt

Désactiver le bouton ou le paramètre non cliquable ne suffit pas si vous effectuez un travail de calcul intensif 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 et que vous pouvez remplacer, qui résout ce problème en ignorant les clics en 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 identique à 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);
40
Ken

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!");
            }
     };
39
jinshiyi11

Vous pouvez le faire de manière très élégante avec Kotlin Extension Functions 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 }
14
Yvgen

J'ai également couru dans un problème similaire, je montrais certains datepicker & timepickers où parfois il a cliqué 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 le temps en fonction de vos besoins. Cette méthode fonctionne pour moi.

11
junto

setEnabled(false) fonctionne parfaitement pour moi.

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

8
saurabh

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

En gros, j'ai créé une classe wrapper qui enveloppe votre vue 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 simplement faire 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: Au-dessus des moyens un peu à l'ancienne maintenant que RxJava est si répandu. Comme d'autres l'ont mentionné, sous 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'

5
j2emanue

La solution réelle à ce problème consiste à 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.

5
EpicOfChaos

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

Il semble que définir vos écouteurs de clic dans onResume et les annuler dans onPause fasse également l'affaire.

2
khendricks

Si quelqu'un cherche encore 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 ira à l'intérieur du if statement chaque fois que l'utilisateur clique sur le View within 1 second, puis le return; sera lancé et le code suivant ne sera pas initié.

2
Rakshit Nawani

Ma solution consiste à utiliser une variable 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);
    }
}

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

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

Click Guard fonctionne bien avec un couteau à beurre

ClickGuard.guard(mPlayButton);
2
thanhbinh84

Pour moi, ne retenir que l'horodatage et le vérifier (que plus d'une seconde s'est écoulée depuis le clic précédent) m'a aidé. 

2
shtolik

vous pouvez aussi utiliser bindings de jake wharton pour y parvenir. Voici un exemple qui compresse 2 secondes entre chaque clic:

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

// remarque: ignorer l'objet v dans ce cas et je pense toujours. 

1
j2emanue

Nous pourrions utiliser le bouton juste synchronisé comme:

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

Bonne chance)

1
Hovanes Mosoyan

La définition de Clickable sur false ne fonctionne pas avec le premier double-clic, mais les doubles-clics suivants sont bloqués. C'est comme si le premier clic sur le délégué de chargement é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;
1
KawBoy

Extension Kotlin permettant un code en ligne concis et des temps d'attente variables pour le 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)
1
Jim
    button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            //to prevent double click
            button.setOnClickListener(null);
        }
    });
1
Indrek Kõue

J'ai trouvé aucune de ces suggestions ne fonctionne si la méthode onClick ne renvoie 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é. (Puisque ceci est fait sur le fil 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. Les attributs de marqueur sont statiques afin d'éviter que tout 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);
}
1
linczy

Je résous ce problème en utilisant deux classes, l'une similaire à la réponse @ jinshiyi11 et l'autre s'appuyant sur un clic explicite, vous ne pouvez cliquer sur un bouton qu'une seule fois. Si vous souhaitez 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);
1
iberck
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
Milan Hlinák

Essayez ceci, ça marche: 

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
King of Masses

Vous pouvez utiliser cette méthode. En utilisant post delay, vous pouvez vous occuper des événements en double-clic.

void debounceEffectForClick (Afficher la vue) {

    view.setClickable(false);

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

        }
    }, 500);
}
1
manmohan

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 utiliser sur le clic du bouton

btnSubmit.setSafeOnClickListener {
    showSettingsScreen()
}
0
jai khambhayta

pour toute personne utilisant la liaison de données:

@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()}"
                   ... />
0
Salah Hammouda

Ceci est ma solution:

if (waitDouble) {
    waitDouble = false;
    Thread thread = new Thread() {
        @Override
        public void run() {
            try {
                sleep(300);
                if (waitDouble == false) {
                    waitDouble = true;
                    singleClick();  //singleClick
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    thread.start();
} else {//DoubleClick
    DoubleClick();
    waitDouble = true;
}

Ou une autre solution:

public class NoDoubleClickUtils {
    private static long lastClickTime;
    private final static int SPACE_TIME = 500;

    public static void initLastClickTime() {
        lastClickTime = 0;
    }

    public synchronized static boolean isDoubleClick() {
        long currentTime = System.currentTimeMillis();
        boolean isClick2;
        if (currentTime - lastClickTime > SPACE_TIME) {
            isClick2 = false;
        } else {
            isClick2 = true;
        }
        lastClickTime = currentTime;
        return isClick2;
    }
}
0
KongJing

Les événements de clic se mettent en file d'attente lorsque le thread d'interface utilisateur est bloqué. Sur un événement de clic de bouton, passez à une tâche en arrière-plan dès que possible pour éviter que les événements de clic ne se mettent en file d'attente les uns derrière les autres.

Déclarez un booléen volatil ou verrouillez-le dans la classe d'activité:

private volatile boolean saving = false;

Créez un bouton avec un onClickListener qui est fermé en enregistrant et démarrez une tâche en arrière-plan pour effectuer le travail:

saveButton.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View view) {
        if (!saving) {
            saving = true;
            new SaveAsyncTask().execute();
        }
    }
});

Créez une classe SaveAsyncTask interne pour effectuer le travail en arrière-plan:

class SaveAsyncTask extends AsyncTask {

    @Override
    protected Object doInBackground(Object[] objects) {
        // Do something here, simulate a 3 second task
        SystemClock.sleep(3000);
        saving = false;
        return null;
    }
}
0
Gary Davies

Je préfère utiliser un bloc de sémaphore. Il est thread-safe et peut être utilisé non seulement pour les boutons.

L'exemple de code est simple:

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
Andrey Hohutkin
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

Si vous cliquez sur le bouton pour ouvrir un nouveau fragment, ajoutez simplement Android:clickable="true" à la vue racine du nouveau fragment en cours d’ouverture.

0
nipun.birla

Solution générique

@Override
        public void onClick(View v) {
            tempDisableButton(v);
            //all the buttons view..
        }

public void tempDisableButton(View viewBtn) {
        final View button = viewBtn;

        button.setEnabled(false);
        button.postDelayed(new Runnable() {
            @Override
            public void run() {
                button.setEnabled(true);
            }
        }, 3000);
    }
0
asok Buzz

J'avais besoin de cela avec des fragments et juste de mettre un drapeau pour contrôler les clics: je veux seulement le premier, les autres ne peuvent pas accéder à l'écouteur

private boolean flag = true;

...

@Override
public void onClick(View view) {

    ...

    if (flag) {

        ...

        listener.onFragmentInteraction(Constants.MY_FRAGMENT, bundle);
        flag = false;
    }

    ...

}

J'espère que cela vous sera utile et corrigez-moi si ce n'est pas correct

0
Jaco

Si vous ne voulez pas (ou ne pouvez pas) utiliser les indicateurs boolean ou remplacer onClickListener, vous pouvez également essayer de déclarer votre activité avec Android:launchMode="singleTop" dans AndroidManifest.xml. 

Comment ça marche?

  • Si une instance de l'activité se trouve en haut de la pile, la nouvelle activité Ne sera pas créée, mais onNewIntent () sera appelée.
  • L'activité peut avoir plusieurs instances
  • Les instances peuvent résider dans différentes tâches
  • Une tâche peut avoir plusieurs instances
0
Alex Dzeshko

Si la seule chose que fait le bouton est de lancer une nouvelle activité, le problème peut être résolu avec le mode de lancement actif " singleTop " et le paramètre FLAG_ACTIVITY_CLEAR_TOP défini sur l'intention. Celui-ci ne fonctionnera pas dans le cas d'une hiérarchie d'activité complexe, mais conviendra pour une structure d'application simple en arborescence.

0
Denis Gladkiy

Seulement 2 étapes, et vous pouvez l'utiliser partout dans votre application.

Étape 1 . créer un singleton pour le manager

package com.im.av.mediator;

import Android.os.SystemClock;

import Java.util.HashMap;

/**
 * Created by ShuHeng on 16/6/1.
 */
public class ClickManager {



    private HashMap<Integer,Long> laskClickTimeMap=new HashMap<Integer,Long>();
    public volatile static ClickManager mInstance =null;

    public static ClickManager getInstance(){
        if (mInstance == null) {
            synchronized(ClickManager.class) {
                if (mInstance == null) {
                    mInstance = new ClickManager();
                }
            }
        }
        return mInstance;
    }
   public boolean isClickable1s(Integer key){
       Long keyLong = laskClickTimeMap.get(key);
       if(keyLong==null){
           laskClickTimeMap.put(key,SystemClock.elapsedRealtime());
           return true;
       }else{
           if (SystemClock.elapsedRealtime() - keyLong.longValue() < 1000){
               return false;
           }else{
               laskClickTimeMap.put(key,new Long(SystemClock.elapsedRealtime()));
               return true;
           }
       }
   }
}  

Étape 2 . ajoutez une ligne pour éviter les clics multiples. 

@Override
public void onClick(View v) {
    // TODO Auto-generated method stub
    int id = v.getId();
    if (id == R.id.iv_back) {
        if(!ClickManager.getInstance().isClickable1s(R.id.iv_back))return;
        //do something
    } else if (id == R.id.iv_light) {
        if(!ClickManager.getInstance().isClickable1s(R.id.iv_light))return;
        //do something
    } else if (id == R.id.iv_camerarotate) {
        if(!ClickManager.getInstance().isClickable1s(R.id.iv_camerarotate))return;
           //do something
    } else if (id == R.id.btn_delete_last_clip) {
        if(!ClickManager.getInstance().isClickable1s(R.id.btn_delete_last_clip))return;
          //do something

    } else if (id == R.id.iv_ok) {
        if(!ClickManager.getInstance().isClickable1s(R.id.iv_ok))return;
        //do something
    }
}
0
shuheng