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


当前回答

下面的代码将防止用户点击多次在几分之一秒内,只允许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();
    }
}

其他回答

这个解决方案(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
        }
    }
}

这个解决方案既快速又简洁。

基本上你只是在应用程序的基本样式中防止双击,并在点击监听器上实现标准。这就像一种魔力,在不同的观点的同时进行触摸。

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

如果你的应用程序使用某种手势事件,这不是正确的答案。

我的解决方案是

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

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

Or

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