在安卓系统中防止双击按钮的最佳方法是什么?


当前回答

下面是一个OnClickListener代理,它可以根据qezt的答案阻止连续的单击。

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

其他回答

我希望这能帮助你,把代码放在你的事件处理程序。

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

    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次。我用这个方法解决了这个问题:

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

你可以根据自己的需要改变时间。

似乎设置你的点击监听器在onResume和空他们在onPause也有技巧。

我的解决方案是尝试使用一个布尔变量:

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

对我来说,只有记住时间戳并检查它(距离上次点击超过1秒)才有帮助。