216

Androidでボタンのダブルクリックを防ぐための最良の方法は何ですか?

4

53 に答える 53

420

クリック時にラストクリック時間を節約すると、この問題を防ぐことができます。

すなわち

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
    }
}
于 2013-05-13T03:56:40.067 に答える
102

setEnabled(false)ユーザーがボタンをもう一度クリックしても安全になるまで、ボタンを無効にします。

于 2011-04-09T23:56:23.580 に答える
64

私の解決策は

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!");
            }
     };
于 2013-12-19T03:32:09.930 に答える
44

onClick()で計算量の多い作業を行っている場合は、ボタンを無効にするか、クリック不可に設定するだけでは不十分です。ボタンを無効にする前に、クリックイベントがキューに入れられる可能性があるためです。代わりにオーバーライドできるOnClickListenerを実装する抽象基本クラスを作成しました。これにより、キューに入れられたクリックを無視することでこの問題が修正されます。

/** 
 * 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);
于 2012-03-30T21:49:52.623 に答える
41

Kotlin拡張関数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 }
于 2018-01-09T12:33:02.817 に答える
22

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

使用法:

button.setOnSingleClickListener { ... }

またはスロットルを制御するための追加パラメータを使用

class OnClickListenerThrottled(private val block: () -> Unit, private val wait: Long) : View.OnClickListener {

    private var lastClickTime = 0L

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

        block()
    }
}

/**
 * A throttled click listener that only invokes [block] at most once per every [wait] milliseconds.
 */
fun View.setOnClickListenerThrottled(wait: Long = 1000L, block: () -> Unit) {
    setOnClickListener(OnClickListenerThrottled(block, wait))
}

使用法:

button.setOnClickListenerThrottled(2000L) { /** some action */}
or
button.setOnClickListenerThrottled { /** some action */}
于 2019-09-16T15:21:11.810 に答える
17

同様の問題が発生しました。日付ピッカーと時間ピッカーを表示していて、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);
}

要件に応じて時間を変更できます。

于 2013-09-28T21:25:21.777 に答える
15

私はそれが古い質問であることを知っていますが、私はこの一般的な問題を解決するために私が見つけた最良の解決策を共有します

        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(
        ()-> view.setEnabled(true),
        500
    );
}
于 2017-11-30T19:10:25.603 に答える
9

setEnabled(false)私にとっては完璧に機能します。

アイデアは、私が最初に書いて、ボタンの最初のクリックで{ setEnabled(true); }それを作るということです。false

于 2012-09-12T17:38:51.773 に答える
8

この問題の実際の解決策は、ボタンをグレー表示するsetEnabled(false)と、2回目のクリックを受け取れないようにするsetClickable(false)を使用することです。これをテストしたところ、非常に効果的であるようです。

于 2011-12-16T05:39:57.497 に答える
8

誰かがまだ短い答えを探しているなら、あなたは以下のコードを使うことができます

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

if statementこのコードは、ユーザーがをクリックするたびに内部に入りView within 1 second、その後、return;が開始され、それ以降のコードは開始されません。

于 2018-01-09T11:30:38.243 に答える
6

次のように同期したボタンを使用できます。

例1(Java)

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

同期を使用した例2(kotlin)

myButton.setOnClickListener { view ->
            synchronized(view) {
                view.isEnabled = false

                // do something

                view.postDelayed({ view.isEnabled = true }, 500L)
            }
        }

幸運を)

于 2018-05-15T07:51:25.223 に答える
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   
                }
            }
        });

更新:ビュー拡張機能を使用したKotlinソリューション

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)
    }
}
于 2018-08-22T03:19:20.043 に答える
6

Kotlinで

button.setOnClickListener { 
    it?.apply { isEnabled = false; postDelayed({ isEnabled = true }, 400) } //400 ms
    //do your work
}
于 2019-11-30T20:04:37.173 に答える
5

私の状況では、ボタンビューを使用していて、クリックが速すぎました。クリック可能を無効にして、数秒後に再度有効にします...

基本的に、ViewsonClickListenerをラップするラッパークラスを作成しました。必要に応じて、カスタム遅延を設定することもできます。

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が非常に普及している今、少し古いやり方を上回っています。他の人が述べているように、Androidでは、スロットルを使用してクリックを遅くすることができます。ここに1つの例があります:

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

このライブラリを使用できます。 implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'

于 2017-03-16T18:45:23.823 に答える
5

クリックガードはバターナイフでうまく機能します

ClickGuard.guard(mPlayButton);
于 2017-09-08T08:51:41.357 に答える
5

Kotlinはクラス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)
    }
}

baseClassなどで関数を作成します

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

ボタンクリックで使用します

btnSubmit.setSafeOnClickListener {
    showSettingsScreen()
}
于 2019-07-04T04:29:55.763 に答える
5

以下のコードは、ユーザーが数分の1秒以内に複数回クリックするのを防ぎ、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();
    }
}
于 2019-12-10T10:04:01.223 に答える
4
    button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            //to prevent double click
            button.setOnClickListener(null);
        }
    });
于 2015-10-05T07:04:43.627 に答える
4

onClickメソッドがすぐに返されない場合、これらの提案はどれも機能しないことがわかりました。タッチイベントはAndroidによってキューに入れられ、次のonClickは、最初のイベントが終了した後にのみ呼び出されます。(これは1つのUIスレッドで行われるため、これは実際には正常です。)onClick関数が終了した時刻と1つのブール変数を使用して、指定されたonClickが実行されているかどうかをマークする必要がありました。これらのマーカー属性は両方とも静的であり、onClickListenerが同時に実行されるのを防ぎます。(ユーザーが別のボタンをクリックした場合)OnClickListenerをこのクラスに置き換えるだけで、onClickメソッドを実装する代わりに、抽象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);
}
于 2016-03-01T15:34:36.283 に答える
4

この方法を使用できます。ポストディレイを使用することで、ダブルクリックイベントに対処できます。

void debounceEffectForClick(View view){

    view.setClickable(false);

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

        }
    }, 500);
}
于 2018-01-16T07:22:52.213 に答える
4

簡潔なインラインコードと可変のダブルクリック待機時間を可能にするKotlin拡張機能

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)
于 2018-07-12T15:12:12.530 に答える
3

私にとっては、タイムスタンプを覚えてそれをチェックする(前回のクリックから1秒以上経過した)だけで役に立ちました。

于 2012-11-26T12:12:08.970 に答える
3

クリックリスナーをonResumeに設定し、onPauseでnullにすることも、うまくいくようです。

于 2011-05-12T13:03:25.830 に答える
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 );
    }
于 2014-09-25T08:25:06.783 に答える
3

これを実現するために、jakewhartonによる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
                });

//注:この場合、オブジェクトvは無視してください。私は、常にそう思います。

于 2017-08-12T18:21:24.573 に答える
3

ジムの答えに追加すると、コードをより簡潔にすることができます。

fun View.setOnSingleClick(onClick: () -> Unit) {
    var lastClickTime = 0L
    setOnClickListener {
        if (currentTimeMillis() > lastClickTime + 750) onClick()
        lastClickTime = currentTimeMillis()
    } 
}

使用法:

aView.setOnSingleClick {  }
于 2019-11-05T16:10:23.670 に答える
3

私の解決策(Kotlin):

class OnDebouncedClickListener(private val delayInMilliSeconds: Long, val action: () -> Unit) : View.OnClickListener {
    var enable = true

    override fun onClick(view: View?) {
        if (enable) {
            enable = false
            view?.postDelayed(delayInMilliSeconds) { enable = true }
            action()
        }
    }
}

fun View.setOnDebouncedClickListener(delayInMilliSeconds: Long = 500, action: () -> Unit) {
    val onDebouncedClickListener = OnDebouncedClickListener(delayInMilliSeconds, action)
    setOnClickListener(onDebouncedClickListener)
}

使用する :

button.apply {       
            setOnDebouncedClickListener {
                //your action on click
            }
        }
于 2020-01-09T14:49:03.097 に答える
2

Clickableをfalseに設定しても、最初のダブルクリックでは機能しませんが、それ以降のダブルクリックはブロックされます。これは、最初のクリックデリゲートの読み込みが遅く、最初のクリックが完了する前に2番目のクリックがキャプチャされたかのようです。

        Button button = contentView.FindViewById<Button>(Resource.Id.buttonIssue);
        button.Clickable = false;
        IssueSelectedItems();
        button.Clickable = true;
于 2012-03-28T15:57:36.427 に答える
2

この問題は、@ jinshiyi11の回答に似た2つのクレースを使用して修正します。注釈は明示的なクリックに基づいています。この場合、ボタンは1回だけクリックできます。別のクリックが必要な場合は、明示的に指定する必要があります。

/**
 * 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);
于 2015-04-12T18:06:59.203 に答える
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");
    }
});
于 2016-11-06T20:16:05.957 に答える
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
    }
});
于 2016-12-14T13:09:36.153 に答える
2

Javaにはネイティブのデバウンスクリックリスナーがあります

view.setOnClickListener(new DebouncedOnClickListener(1000) { //in milisecs
            @Override
            public void onDebouncedClick(View v) {
                //action
            }
        });
于 2020-09-29T08:31:15.680 に答える
2

このソリューション(Kotlin)は私に効果があります:

abstract class SingleClickListener : View.OnClickListener {
    private val MIN_CLICK_INTERVAL: Long = 1000
    private var mLastClickTime: Long = 0

    abstract fun onSingleClick(v: View?)

    override fun onClick(v: View?) {
        if (mLastClickTime <= 0) {
            mLastClickTime = SystemClock.uptimeMillis()
            onSingleClick(v)
            return
        }

        if (SystemClock.uptimeMillis() - mLastClickTime <= MIN_CLICK_INTERVAL) {
            return
        }

        mLastClickTime = SystemClock.uptimeMillis()

        onSingleClick(v)
    }
}

使用法:

someView.setOnClickListener(object : SingleClickListener() {
    override fun onSingleClick(v: View?) {
        v?.also { klik(it) }
    }
})

または、ビューにClickListenerを簡単に追加するための拡張関数を作成します。

fun View.click(klik: (View) -> Unit) {
    this.setOnClickListener(object : SingleClickListener() {
        override fun onSingleClick(v: View?) {
            v?.also { klik(it) }
        }
    })
}

// Usage
class XPerimentActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_xperiment_layout)

        submit_button.click {
           // do your magic
        }
    }
}
于 2020-11-01T06:18:24.450 に答える
1

たった2ステップで、アプリケーションのどこでも使用できます。

ステップ1。マネージャーへのシングルトンを作成する[マルチクリックを回避する]

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

ステップ2。複数クリックを避けるために1行追加します。

@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
    }
}
于 2016-06-02T02:10:40.363 に答える
1

Kotlin拡張機能付き:

fun View.onSingleClick(action: (v: View) -> Unit) {
    setOnClickListener(object : View.OnClickListener {
        override fun onClick(v: View) {
            isEnabled = false
            action(v)
            postDelayed({ isEnabled = true }, 700)
        }
    })
}

利用方法:

button.onSingleClick { myAction() }
于 2021-01-10T09:09:25.283 に答える
1

以下は、すべてのビューで機能する拡張機能を備えたkotlinの方法であり、urUtilsまたは任意のファイルで以下の機能を維持します

fun View.preventDoubleClick() {
this.isEnabled = false
this.postDelayed( { this.isEnabled = true }, 1000)
}

以下は、フラグメントまたはアクティビティからの使用方法です。

anyIdOfView?.setOnClickListener {
it.preventDoubleClick()
YourAction()
}
于 2021-11-01T15:51:17.803 に答える
0

booleanフラグやオーバーライドを使用したくない(または使用できない)場合は、AndroidManifest.xmlでonClickListenerアクティビティを宣言することもできます。android:launchMode="singleTop"

どのように機能しますか?

  • アクティビティのインスタンスがスタックの最上位にある場合(新しいアクティビティは作成されません)、代わりにonNewIntent()が呼び出されます。
  • アクティビティには複数のインスタンスを含めることができます
  • インスタンスはさまざまなタスクに常駐できます
  • 1つのタスクに複数のインスタンスを含めることができます
于 2014-06-26T07:23:34.183 に答える
0

私はセマフォブロックを使用することを好みます。スレッドセーフで、ボタンだけでなく使用できます。

コードサンプルは単純です。

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

}
于 2015-05-01T09:17:10.720 に答える
0

ボタンが行う唯一のことが新しいアクティビティの起動である場合、問題は「 singleTop」アクティビティ起動モードとFLAG_ACTIVITY_CLEAR_TOPをインテントに設定することで解決できます。これは、複雑なアクティビティの階層の場合には機能しませんが、単純なツリーのようなアプリケーション構造には適しています。

于 2015-05-06T03:53:36.650 に答える
0

一般的なソリューション

@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);
    }
于 2016-05-09T15:14:56.410 に答える
0

フラグメントでのウォーキングが必要で、クリックを制御するためのフラグを設定するだけです。最初の1つだけが必要で、他のユーザーはリスナーにアクセスできません。

private boolean flag = true;

...

@Override
public void onClick(View view) {

    ...

    if (flag) {

        ...

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

    ...

}

それがお役に立てば幸いです、そしてそれが正しくないなら私を訂正してください

于 2016-08-04T17:18:59.883 に答える
0

UIスレッドがブロックされると、クリックイベントがキューに入れられます。ボタンクリックイベントでは、クリックイベントが互いに遅れないように、できるだけ早くバックグラウンドタスクに変更してください。

揮発性ブール値を宣言するか、アクティビティクラス内でロックします。

private volatile boolean saving = false;

保存してゲートされるonClickListenerを使用してボタンを作成し、バックグラウンドタスクを開始して作業を実行します。

saveButton.setOnClickListener(new View.OnClickListener() {

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

バックグラウンドで作業を行うための内部SaveAsyncTaskクラスを作成します。

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;
    }
}
于 2016-10-11T12:13:25.613 に答える
0

これが私の解決策です:

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

または別の解決策:

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;
    }
}
于 2016-10-26T10:19:20.477 に答える
0

ボタンをクリックしたときに新しいフラグメントを開いている場合は、開いている新しいフラグメントandroid:clickable="true"のルートビューに追加するだけです。

于 2017-04-05T10:05:23.807 に答える
0
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;
}
于 2018-05-04T06:53:36.287 に答える
0

データバインディングを使用している人のために:

@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()}"
                   ... />
于 2019-05-31T14:36:26.560 に答える
0

ボタンをクリックするとfalseに設定し、ボタンをもう一度クリック可能にする必要がある場合はtrueに設定するのが正しい方法です。たとえば、次のシナリオを考えてみます。ボタンをクリックしたときにサービスコールを発信し、サービスが完了したらダイアログを表示します。このため、ボタンがクリックされるとsetClickable(false)を設定でき、サービスが応答したら、カスタムダイアログに渡す参照を介してsetClicklable(true)を実行します。ダイアログがisShowing()を呼び出すと、リスナーとsetClicklable(true)をトリガーできます。

于 2019-09-22T07:26:43.963 に答える
0

このソリューションは迅速かつ適切です。

基本的には、アプリの基本スタイルからのダブルタッチを防ぎ、クリックリスナーに標準を実装するだけです。これは、異なるビューと同時にタッチするチャームのように機能します。

<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
...
<item name="android:splitMotionEvents">false</item>
<item name="android:windowEnableSplitTouch">false</item>
</style>

アプリが何らかのジェスチャーイベントを使用している場合、これは正しい答えではありません。

于 2019-10-28T20:51:51.840 に答える
0

このKotlin拡張機能を試してください:

private var lastClickTime = 0L

fun View.click(action: () -> Unit) {
    setOnClickListener {
        if (SystemClock.elapsedRealtime() - lastClickTime < 600L)
            return@setOnClickListener
        lastClickTime = SystemClock.elapsedRealtime()
        action()
    }
}

また、アプリのさまざまな部分が同時にクリックされるのを防ぎます。

于 2020-06-15T10:26:35.510 に答える
0

これは、 qeztの回答に基づいて、連続クリックを防ぐOnClickListener プロキシです。

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

public class MultiClickGuard implements View.OnClickListener {    

    private long mLastClickTime;

    private final int mThresholdMillis;
    private final View.OnClickListener mListener;

    public MultiClickGuard(View.OnClickListener listener, int thresholdMillis) {
        if (listener == null) {
            throw new NullPointerException("Null OnClickListener");
        }
        if (thresholdMillis < 0) {
            throw new IllegalArgumentException("Negative click threshold: " + thresholdMillis);
        }

        mListener = listener;
        mThresholdMillis = thresholdMillis;
    }

    @Override
    public void onClick(View v) {
        // Using a time threshold to prevent successive clicks.
        if (SystemClock.elapsedRealtime() - mLastClickTime < mThresholdMillis) {
            return;
        }
        mLastClickTime = SystemClock.elapsedRealtime();

        // Forward the click event to the *real* listener.
        mListener.onClick(v);
    }
}

使用例

button.setOnClickListener(new MultiClickGuard(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // do something
    }
}, 1000));

button.setOnClickListener(new MultiClickGuard(v -> {...}, 1000));
button.setOnClickListener(new MultiClickGuard(v -> doSomething(), 1000));

アクティビティの複数のインスタンスの開始を防止しようとしている状況では、起動モードを指定することを検討してください。タスクとバックスタックを理解する。これは信頼できる方法です。

ダイアログフラグメントの複数のインスタンスを開かないようにする場合は、フラグメントマネージャにダイアログがすでに含まれているかどうかを確認できますgetSupportFragmentManager().findFragmentByTag(tag)

于 2021-03-10T15:01:51.410 に答える
0

乗算btnsのクリックを防ぎます

使用:

private val disposables = CompositeDisposable()
private val clickInteractor = ClickInteractor(disposables)
...
button1.setOnClickListener{
     clickInteractor.click {
          Toast.makeText(context, "Btn1", Toast.LENGTH_LONG).show()
     }
}
button2.setOnClickListener{
     clickInteractor.click {
          Toast.makeText(context, "Btn2", Toast.LENGTH_LONG).show()
     }
}

ClickInteractor.kt:

class ClickInteractor constructor(disposables: CompositeDisposable) {
    private val performPublish = PublishSubject.create<ClickInteractorCallback>()

    init {
        performPublish
            .subscribeOn(Schedulers.io())
            .observeOn(Schedulers.io())
            .throttleFirst(1, TimeUnit.SECONDS, Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnNext { callback ->
                callback.invoke()
            }
            .retry()
            .execute(disposables)
    }

    fun click(callback: ClickInteractorCallback) {
        performPublish.onNext(callback)
    }
}

typealias ClickInteractorCallback = () -> Unit
于 2021-04-15T15:11:21.843 に答える
-3

より好ましい解決策は、

onclick(){
  btn.setEnabled(false);
  btn.setClickable(false);
  //yourwork
  myWork();
}

myWork(){
 //your tasks.
 btn.setEnabled(true);
 btn.setClickable(true);
}

リンクは簡単に無視できるので、これを何度も繰り返す必要がありました

于 2013-09-18T03:23:29.063 に答える