Android एक बटन पर डबल क्लिक करने से रोकता है


177

Android में एक बटन पर दोहरे क्लिक को रोकने का सबसे अच्छा तरीका क्या है?


3
क्विज़ के समाधान को केवल पूर्ण रूप से व्यावहारिक रूप से देखें
Gennadiy Ryabkin

3
qezt के समाधान को स्वीकार किया जाना चाहिए था, ताकि जो लोग इस पृष्ठ पर जाएं, वे setEnabled (गलत) का उपयोग करने का दोष जानें।
लवफोरड्रायड

अंतिम-क्लिक-टाइम समाधान का उपयोग करके आप मेरी लाइब्रेरी आज़मा सकते हैं: github.com/RexLKW/SClick
Rex Lam

1
@Androider कृपया अपना सर्वश्रेष्ठ उत्तर बदलें
Amir133

जवाबों:


87

setEnabled(false)उपयोगकर्ता द्वारा इसे फिर से क्लिक करने के लिए सुरक्षित होने तक बटन को अक्षम करें।


47
setEnabled (झूठा) पर्याप्त "तेज" काम नहीं करता है। मैंने एक बटन के लिए एक View.OnClickListener.onClick (दृश्य) सेट किया है। पहली बात जो मैं onClick में करता हूं () एक लॉग-स्टेटमेंट लिख रहा है, दूसरा स्टेटमेंट बटन है ।setEnabled (गलत)। एमुलेटर में फास्ट-डबल-क्लिक करने पर मुझे लॉग-स्टेटमेंट दो बार दिखाई देता है! यहां तक ​​कि उसके बाद एक setClickable (झूठा) जोड़ने पर भी, लॉग-स्टेटमेंट दो बार दिखाई देता है।
QQQuestions

हम्म, शायद onClick () के अंत में setEnabled (सच) तक कोड को इतनी जल्दी निष्पादित किया जा रहा है कि यह पहले से ही फिर से सक्षम हो ...
QQQuestions

91
मुझे भी ऐसी ही समस्या का समाधान करना पड़ा था। एक सहायक सज्जन के अनुसार, एंड्रॉइड वास्तव में क्लिक को कतारबद्ध करता है, इसलिए यह महत्वपूर्ण नहीं है कि आपका ऑनक्लिक () कोड निष्पादित कितनी तेजी से या धीमा है; केवल आप कितनी तेजी से बटन क्लिक करते हैं। अर्थात। आपने बटन को पहले ही निष्क्रिय कर दिया होगा, लेकिन क्लिक कतार पहले से ही दो या तीन क्लिकों से भरी हुई है और बटन को अक्षम करने से कतारबद्ध क्लिकों के वितरण पर कोई प्रभाव नहीं पड़ता है। (हालांकि शायद यह होना चाहिए?)
निक

3
वह दुर्लभ क्षण जब आप 'किसी' को देखते हैं, सटीक उत्तर देते हैं और पूछे गए प्रश्न का उत्तर नहीं देते हैं ..: P
राहुल

यह हमेशा सही समाधान नहीं है। यदि आपका ऑनक्लिक महंगा ऑपरेशन है, तो बटन तेजी से अक्षम नहीं होगा। पूर्ण-प्रूफ समाधान IMHO अंतिम क्लिक समय का उपयोग करने के लिए है, लेकिन यदि आप ऑपरेशन को थोड़ी देर तक चलाने की उम्मीद करते हैं, तो उस पर फिर से उपयोगकर्ता टैपिंग से बचने के लिए बटन को अक्षम करें (जैसे लॉगिन)।
सारंग

368

अंतिम क्लिक समय की बचत जब क्लिक करने से इस समस्या से बचाव होगा।

अर्थात

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

21
यह एकमात्र समाधान है जो वास्तव में एक डबल क्लिक को रोकता है। मैं सिर्फ एक घंटे का समय दूसरों के लिए कोशिश कर रहा हूं क्योंकि यह तरीका बहुत अच्छा है, लेकिन उनमें से कोई भी इस एक दृश्य के अलावा एक त्वरित डबल टैप को नहीं रोक सकता है। Google कृपया इसे ठीक करें :)
ashishduh

6
यह समाधान ठीक काम करता है। यह समाधान तब भी काम करता है जब आपके पास स्क्रीन पर कई बटन होते हैं और आप समय पर केवल एक बटन पर क्लिक करना चाहते हैं।
शून्य

12
यदि आप डबल क्लिक करते हैं तो यह पूरी तरह से डबल क्लिक को रोकता नहीं है।
लोक

4
सबसे अच्छा जवाब, यह शीर्ष पर होना चाहिए
जेनडाई रियाबिन

3
यह समाधान सही उत्तर होना चाहिए ... setEnabled (झूठा) पर्याप्त नहीं है।
19lo में heloisasim

55

मेरा समाधान है

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

}

उपयोग OnClickListener के समान है लेकिन इसके बजाय onSingleClick () को ओवरराइड करें:

mTextView.setOnClickListener(new OnSingleClickListener() {
            @Override
            public void onSingleClick(View v) {
                if (DEBUG)
                    Log.i("TAG", "onclick!");
            }
     };

1
आसान और सही स्वचालित रूप से दोहरे स्पर्श को रोकने के लिए।
बेंजामिन पीट

1
यदि आप डबल क्लिक करते हैं तो यह पूरी तरह से डबल क्लिक को रोकता नहीं है।
लोक

1
महान समाधान। मैंने अभी MIN_CLICK_INTERVAL = 1000 को बदला;
निजाम

5
अगर मुझे हर 0.5 सेकंड में सही बटन लगाना था, तो मेरे बाद के किसी भी क्लिक को नहीं मिलेगा क्योंकि mLastClickTime को प्रत्येक क्लिक को अपडेट किया जाएगा। आप अंतराल की जाँच करने के बाद मेरा सुझाव mLastClickTime असाइन करना होगा।
k2col

mLastClickTime = currentClickTime; अगर (बीता हुआ समय के बाद रखा जाना चाहिए <= MIN_CLICK_INTERVAL) वापसी;
लोयिा

41

बटन को निष्क्रिय करना या अशुद्ध सेट करने के लिए पर्याप्त नहीं है यदि आप onClick () में कम्प्यूटेशनल रूप से गहन कार्य कर रहे हैं क्योंकि बटन को निष्क्रिय करने से पहले क्लिक ईवेंट को कतारबद्ध किया जा सकता है। मैंने एक एब्सट्रैक्ट बेस क्लास लिखा है जो ऑनक्लीक्लिनेर को लागू करता है जिसे आप इसके बजाय ओवरराइड कर सकते हैं, जो किसी भी कतारबद्ध क्लिक को अनदेखा करके इस समस्या को ठीक करता है:

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

उपयोग OnClickListener के समान है लेकिन इसके बजाय OnOneClick () को ओवरराइड करें:

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

कोड के लिए धन्यवाद। यहाँ जो आपने लिखा है उसके आधार पर मैंने ऐसी ही क्लास बनाई है जो क्लिक करने पर बटन को रोकती है या माता-पिता को छिपाया जाता है - यह मज़ेदार है कि क्लिक के तुरंत बाद अगर आप बटन छिपाते हैं तो भी एंड्रॉइड क्लिक पर कतार लगा देगा।
nikib3ro

1
मैं एक ऐसी ही समाधान है - तुम सिर्फ एक्सएमएल में इस वर्ग का उपयोग कर सकते हैं और यह आप के लिए clickListeners लपेटो जाएगा github.com/doridori/AndroidUtilDump/blob/master/android/src/...
डोरी

2
यह एक अच्छा समाधान है, लेकिन onClick () और रीसेट () को सिंक्रनाइज़ करने की आवश्यकता है, अन्यथा एक डबल-क्लिक में चुपके हो सकता है
टॉम 8

6
@TomanMoney, कैसे? क्या सभी क्लिक ईवेंट एक ही UI थ्रेड पर नहीं होते हैं?
केन

@ डोरी लिंक मृत है
naXa

36

आप इसे कोटलिन एक्सटेंशन फ़ंक्शंस और RxBinding के साथ बहुत फैंसी तरीके से कर सकते हैं

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

या

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

और फिर बस:

View.clickWithDebounce{ Your code }

अधिक उत्कीर्णन
सर्ग बरलाका

3
आरएक्स के लिए डेब्यू यहां अच्छा काम नहीं करेगा। इसके बजाय "थ्रॉटलफर्स्ट" को बेहतर तरीके से फिट किया जाना चाहिए। यहां डेमो . nimius.net/debounce_throttle उदाहरण है कि वे कैसे भिन्न हैं। पुनश्च: और वास्तव में आपका क्लिकथाइब्यूड कार्यान्वयन थ्रॉटल कार्यान्वयन है, न कि बहस
krossovochkin

13

मैं भी इसी तरह की समस्या में भागता हूं, मैं कुछ तारीख और समय-सारणी प्रदर्शित कर रहा था जहां कभी-कभी 2 बार क्लिक होता है। मैंने इसे इसके द्वारा हल किया है

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

आप अपनी आवश्यकता के आधार पर समय बदल सकते हैं। यह विधि मेरे लिए काम करती है।


यह वास्तविक समाधान है, क्योंकि यह समय बीत जाने के बाद स्वचालित रूप से बटन को फिर से सक्रिय करता है। यदि आप दो बार जल्दी से क्लिक करते हैं तो अन्य समाधान बटन को स्थायी रूप से ब्लॉक कर देते हैं। यह समाधान समस्या को ठीक करता है! धन्यवाद
Néstor

10

setEnabled(false) मेरे लिए पूरी तरह से काम करता है।

विचार यह है कि मैं { setEnabled(true); }शुरुआत में लिख रहा हूं और बस इसे falseबटन के पहले क्लिक पर बनाएं ।


9

मुझे पता है कि यह एक पुराना सवाल है, लेकिन मैं इस सामान्य समस्या को हल करने के लिए सबसे अच्छा समाधान साझा करता हूं

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

और दूसरी फाइल में, जैसे 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);
}

8

इस समस्या का वास्तविक समाधान सेटइन्फैक्टिव (गलत) का उपयोग करना है जो बटन को पकड़ लेता है, और सेटक्लिक करने योग्य (झूठा) जो इसे बनाता है इसलिए दूसरा क्लिक प्राप्त नहीं किया जा सकता है मैंने इसे परीक्षण किया है और यह बहुत प्रभावी लगता है।


7

यदि कोई अभी भी एक छोटे से उत्तर की तलाश में है तो आप नीचे दिए गए कोड का उपयोग कर सकते हैं

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

if statementजब भी उपयोगकर्ता इस पर क्लिक करेगा View within 1 secondतो यह कोड अंदर चला जाएगा और फिर return;पहल शुरू कर दी जाएगी और आगे कोड शुरू नहीं होगा।


2
यह स्वीकृत उत्तर होना चाहिए। सुपर सरल और यह काम करता है भले ही आप बहुत तेजी से क्लिक करें! इसके लिए धन्यवाद।
जियोफ़रॉय CALA

7

कश्मीर 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))
}

उपयोग:

button.setOnSingleClickListener { ... }

6

मेरा समाधान एक 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   
                }
            }
        });

अद्यतन : कोटलिन समाधान, दृश्य विस्तार का उपयोग करते हुए

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

5

मक्खन चाकू के साथ क्लिक गार्ड अच्छी तरह से काम करता है

ClickGuard.guard(mPlayButton);

4
बटन पर डबल क्लिक करें हैंडल के लिए separete? हा
सर्ग बरलाका

क्या मैं कस्टम बटन के अंदर इसका उपयोग कर सकता हूं?
आरा बदालयन

@AraBadalyan का 'अंदर' से क्या मतलब है? गार्ड विधि के लिए बस अपने कस्टम बटन को परम के रूप में पास करें। तब आपका बटन डबल क्लिक से सुरक्षित रहेगा
thanhbinh84

मेरा मतलब है कि मैं उन सभी गतिविधियों में ClickGuard.guard (mPlayButton) को जोड़ना नहीं चाहता हूं जो ऑनक्लिक का उपयोग करते हैं। मैं CustomButton हद बटन बनाना चाहते हैं और ClickGuard को CustomButton के अंदर रखना चाहते हैं। लेकिन जब मैं CustomGutton कंस्ट्रक्टर में ClickGuard जोड़ता हूं तो यह काम नहीं करता था।
आरा बदालयन

@AraBadalyan यह सही है। यह उस तरह से काम नहीं करता है।
thanhbinh84

5

मेरी स्थिति में मैं एक बटन दृश्य का उपयोग कर रहा था और यह बहुत तेज़ी से क्लिक ले रहा था। बस क्लिक करने योग्य को अक्षम करें और कुछ सेकंड के बाद इसे फिर से सक्षम करें ...

मूल रूप से मैंने एक आवरण वर्ग बनाया है जो आपके दृश्य के चारों ओर लपेटता है onClickListener। यदि आप चाहें तो आप एक कस्टम विलंब भी सेट कर सकते हैं।

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

और इसे कॉल करने के लिए बस ऐसा करें:

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

या अपनी देरी प्रदान करें:

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

अद्यतन: ऊपर का तरीका अब थोड़ा पुराना है कि RxJava बहुत प्रचलित है। जैसा कि दूसरों ने उल्लेख किया है, एंड्रॉइड में हम क्लिक को धीमा करने के लिए एक थ्रॉटल का उपयोग कर सकते हैं। यहाँ एक उदाहरण है:

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

आप इसके लिए इस लाइब्रेरी का उपयोग कर सकते हैं: implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'


4
    button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            //to prevent double click
            button.setOnClickListener(null);
        }
    });

4

आप इस विधि का उपयोग कर सकते हैं। पोस्ट देरी का उपयोग करके आप डबल क्लिक घटनाओं के लिए देखभाल कर सकते हैं।

शून्य डिबेटइफेक्टफॉरक्लिक (दृश्य देखें) {

    view.setClickable(false);

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

        }
    }, 500);
}

4

कोटलिन एक्सटेंशन जो संक्षिप्त इनलाइन कोड और चर डबल क्लिक प्रतीक्षा समय के लिए अनुमति देता है

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)

बहुत बढ़िया, हर किसी को इसका उपयोग करना चाहिए, इसका बिल्कुल अच्छा टुकड़ा कोड और महान कारण है कि हर किसी को कोटलिन में पलायन करना चाहिए।
अचमद नूफ़ल सफ़ीक

नेकलेस हो सकता है अगर वेटमिलिस सिर्फ हार्डकोड है, तो बाहरी कोष्ठक को समाप्त किया जा सकता है।
विंडराइडर

4

नीचे दिया गया कोड सेकंड के एक अंश के भीतर कई बार क्लिक करने के लिए उपयोगकर्ता को रोक देगा और केवल 3 सेकंड के बाद ही अनुमति देगा।

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

3

ऐसा लगता है कि अपने क्लिक श्रोताओं को onResume में सेट करना और उन्हें ऑन-आउट करना बंद करना भी चालबाजी करता है।


3

मेरे लिए केवल टाइमस्टैम्प को याद रखना और उसके खिलाफ जांच करना (कि पिछले क्लिक से 1 सेकंड से अधिक समय बीत गया) ने मदद की।


3

मुझे उम्मीद है कि यह आपकी मदद कर सकता है, आप घटना हैंडलर में कोड डाल सकते हैं।

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

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

3

मैंने पाया कि इनमें से कोई भी सुझाव काम नहीं करता है अगर ऑनक्लिक विधि तुरंत वापस नहीं आती है। टच इवेंट को Android द्वारा पंक्तिबद्ध किया जाता है और अगले ऑनक्लिक को केवल पहले एक के समाप्त होने के बाद ही कहा जाता है। (चूंकि यह एक यूआई थ्रेड पर किया जाता है, यह वास्तव में सामान्य है।) मुझे उस समय का उपयोग करने की आवश्यकता है जब ऑनक्लिक फ़ंक्शन समाप्त हो गया है + एक बूलियन चर को चिह्नित करने के लिए कि क्या दिए गए ऑनक्लिक चल रहे हैं। एक ही समय में चलने के लिए किसी भी onClickListener से बचने के लिए ये दोनों मार्कर विशेषताएँ स्थिर हैं। (यदि उपयोगकर्ता किसी अन्य बटन पर क्लिक करता है) तो आप इस क्लास में अपने OnClickListener को सरल रूप से बदल सकते हैं और ऑनक्लिक विधि को लागू करने के बजाय आपको अमूर्त एकक्लिक () विधि को लागू करने की आवश्यकता है।

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

3

इसे पूरा करने के लिए आप जेक व्हार्टन द्वारा आरएक्स बाइंडिंग का भी उपयोग कर सकते हैं । यहाँ एक नमूना है जो क्रमिक क्लिकों के बीच 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
                });

// नोट: इस मामले में ऑब्जेक्ट v को नजरअंदाज करें और मुझे हमेशा लगता है।


3

कोटलिन ने सुरक्षित 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)
    }
}

बेसक्लास में एक फंक्शन बनाएं वरना

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

और बटन क्लिक पर उपयोग करें

btnSubmit.setSafeOnClickListener {
    showSettingsScreen()
}

1
एक्सटेंशन के साथ सबसे साफ समाधान! धन्यवाद!
android_dev



2

क्लिक करने योग्य को झूठे पर सेट करना पहले डबल क्लिक पर काम नहीं करता है लेकिन बाद में डबल क्लिक अवरुद्ध हो जाता है। यह ऐसा है जैसे कि लोडिंग क्लिक प्रतिनिधि को पहली बार धीमा करता है और पहला पूरा होने से पहले दूसरा क्लिक पकड़ लिया जाता है।

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

2

मैं दो क्लेसेस का उपयोग करके इस समस्या को ठीक करता हूं, एक @ 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);

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

दृश्य श्रोताओं को हमेशा एक ही धागे (मुख्य) पर बुलाया जाता है, इसलिए उपयोग AtomicBooleanकरने से वास्तव में मदद नहीं मिल सकती है।
WindRider

2

यह कोशिश करो, यह काम कर रहा है:

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
    }
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.