在Android中阻止双击按钮的最佳方法是什么?
答案 0 :(得分:292)
点击时保存最后点击时间可以防止出现此问题。
即
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
}
}
答案 1 :(得分:68)
禁用setEnabled(false)
按钮,直到用户再次点击它为止是安全的。
答案 2 :(得分:41)
如果您在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);
答案 3 :(得分:39)
我的解决方案是
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!");
}
};
答案 4 :(得分:17)
您可以使用Kotlin Extension Functions和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 }
答案 5 :(得分:11)
我也遇到了类似的问题,我正在显示一些日期选择器&amp;时间戳有时会点击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);
}
您可以根据需要更改时间。这种方法适合我。
答案 6 :(得分:8)
setEnabled(false)
非常适合我。
我的想法是在开头编写{ setEnabled(true); }
,然后在第一次点击按钮时将其设为false
。
答案 7 :(得分:5)
这个问题的实际解决方案是使用灰色按钮的setEnabled(false)和setClickable(false)使得它无法接收到第二次点击我已经测试了它并且它似乎非常有效。
答案 8 :(得分:4)
在我的情况下,我使用的是按钮视图,而且点击过快。只需禁用可点击并在几秒钟后再次启用它...
基本上我创建了一个包装你的Views onClickListener的包装类。如果需要,您也可以设置自定义延迟。
yCoordBg1 += BACKGROUND_MOVE_SPEED * Gdx.graphics.getDeltaTime();
yCoordBg2 = yCoordbg1 + yMax; // We move the background, not the camera
if (yCoordBg1 >= 0) {
yCoordBg1 = yMax*(-1); yCoordBg2 = 0;
}
batch.begin();
batch.draw(background1, 0, yCoordBg1);
batch.draw(background2, 0, yCoordBg2);
batch.end();
并调用它只需执行此操作:
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();
}
}));
更新:现在RxJava如此普遍,现在已经过时了。正如其他人所提到的,在android中我们可以使用节流来减慢点击次数。这是一个例子:
mMyButton.setOnClickListener(new OnClickRateLimitedDecoratedListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doSomething();
}
},1000));
您可以使用此库: RxView.clicks(myButton)
.throttleFirst(2000, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.subscribe {
Log.d("i got delayed clicked")
}
}
答案 9 :(得分:3)
K 最简洁的科特林惯用方式:
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 { ... }
答案 10 :(得分:3)
我的解决方案是尝试使用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
}
}
});
答案 11 :(得分:2)
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)
答案 12 :(得分:2)
如果有人仍在寻找简短的答案,您可以使用以下代码
private static long mLastClickTime = 0;
if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) { // 1000 = 1second
return;
}
mLastClickTime = SystemClock.elapsedRealtime();
只要用户点击if statement
,此代码就会进入View within 1 second
,然后return;
将会启动,而其他代码将无法启动。
答案 13 :(得分:2)
我知道这是一个老问题,但我分享了我找到解决这个常见问题的最佳解决方案
/**
* 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);
}
在另一个文件中,例如Utils.java
<p>
<%= label_tag(:sk, "Skills:") %>
<%= text_area_tag :sk, params[:sk], placeholder: "Enter skills", class: "form-control" %>
</p>
答案 14 :(得分:2)
Click Guard适用于Butter Knife
<div class="container-fluid">
<div class="row">
<div class="col-lg-3">
<div id="categorymenu">
<center> <h3>Categorieën</h3> </center>
<ul class="list-group">
<?php foreach (get_categories_h() as $category) : ?>
<li class="list-group-item">
<a href="#"><?php echo $category['name']; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div>
答案 15 :(得分:2)
似乎在onResume中设置你的点击监听器并在onPause中将它们归零也是有用的。
答案 16 :(得分:2)
我的解决方案(科特琳):
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
}
}
答案 17 :(得分:2)
如果onClick方法没有立即返回,我发现这些建议都不起作用。触摸事件由Android排队,下一个onClick仅在第一个完成后调用。 (因为这是在一个UI线程上完成的,这是正常的。) 我需要使用onClick函数完成时的时间+一个布尔变量来标记给定的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);
}
答案 18 :(得分:2)
对我来说,只记住时间戳并检查它(自上次点击后超过1秒)帮助了。
答案 19 :(得分:2)
我希望这可以帮助你,把代码放在你的事件处理程序中。
// --------------------------------------------- -----------------------------------
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 );
}
答案 20 :(得分:2)
此解决方案(科特琳)对我有效:
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
}
}
}
答案 21 :(得分:1)
Java中有一个本机的反跳点击侦听器
import numpy as np
def get_with_default(a, indices, default=0):
# Ensure inputs are arrays
a = np.asarray(a)
indices = tuple(np.broadcast_arrays(*indices))
if len(indices) <= 0 or len(indices) > a.ndim:
raise ValueError('invalid number of indices.')
# Make mask of indices out of bounds
mask = np.zeros(indices[0].shape, np.bool)
for ind, s in zip(indices, a.shape):
mask |= (ind < 0) | (ind >= s)
# Only do masking if necessary
n_mask = np.count_nonzero(mask)
# Shortcut for the case where all is masked
if n_mask == mask.size:
return np.full_like(a, default)
if n_mask > 0:
# Ensure index arrays are contiguous so masking works right
indices = tuple(map(np.ascontiguousarray, indices))
for ind in indices:
# Replace masked indices with zeros
ind[mask] = 0
# Get values
res = a[indices]
if n_mask > 0:
# Replace values of masked indices with default value
res[mask] = default
return res
# Test
print(get_with_default(
np.array([[1,2,3],[4,5,6]]),
(np.array([0, 0, 1, 1, 2, 2]), np.array([1, 2, 2, 3, 3, 5])),
13
))
# [ 2 3 6 13 13 13]
答案 22 :(得分:1)
将Clickable设置为false在第一次双击时不起作用,但后续双击会被阻止。就好像第一次加载点击委托更慢,第二次点击在第一次完成之前被捕获。
Button button = contentView.FindViewById<Button>(Resource.Id.buttonIssue);
button.Clickable = false;
IssueSelectedItems();
button.Clickable = true;
答案 23 :(得分:1)
我们可以使用刚刚同步的按钮:
@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);
}
}
祝你好运)
答案 24 :(得分:1)
您可以使用此方法。通过使用后延迟,您可以照顾双击事件。
void debounceEffectForClick(查看视图){
view.setClickable(false);
view.postDelayed(new Runnable() {
@Override
public void run() {
view.setClickable(true);
}
}, 500);
}
答案 25 :(得分:1)
我使用两个clases解决了这个问题,一个类似于@ jinshiyi11的答案,anoter基于明确的点击,在这里你只能点击一次按钮,如果你想再次点击你必须指出它明确地
/**
* 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);
答案 26 :(得分: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() }
答案 27 :(得分:1)
您也可以使用rx bindings by jake wharton来完成此操作。这是一个在连续点击之间填充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,我想永远。
答案 28 :(得分:1)
Adding to Jim's answer the code can be made more concise:
fun View.setOnSingleClick(onClick: () -> Unit) {
var lastClickTime = 0L
setOnClickListener {
if (currentTimeMillis() > lastClickTime + 750) onClick()
lastClickTime = currentTimeMillis()
}
}
用法:
aView.setOnSingleClick { }
答案 29 :(得分:1)
试试这个,它正在运作:
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
}
});
答案 30 :(得分:1)
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");
}
});
答案 31 :(得分: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();
}
}
答案 32 :(得分:1)
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
//to prevent double click
button.setOnClickListener(null);
}
});
答案 33 :(得分:0)
这是一个 OnClickListener
proxy,它根据 qezt's answer 阻止连续点击。
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));
如果您试图阻止启动多个 Activity 实例,请考虑指定启动模式:Understand Tasks and Back Stack,这是实现此目的的可靠方法。
如果您试图阻止打开一个对话框片段的多个实例,您可以检查片段管理器是否已经包含该对话框,例如getSupportFragmentManager().findFragmentByTag(tag)
。
答案 34 :(得分:0)
在科特林
button.setOnClickListener {
it?.apply { isEnabled = false; postDelayed({ isEnabled = true }, 400) //400 ms
//do your work
}
答案 35 :(得分:0)
This解决方案简洁明了。
基本上,您只需防止应用中的基本样式发生双击即可,并在点击侦听器上实现标准。这就像在不同视图的同时具有触摸感的魅力一样。
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
...
<item name="android:splitMotionEvents">false</item>
<item name="android:windowEnableSplitTouch">false</item>
</style>
如果您的应用使用某种手势事件,那么这不是正确的答案。
答案 36 :(得分:0)
尝试使用此Kotlin扩展功能:
private var lastClickTime = 0L
fun View.click(action: () -> Unit) {
setOnClickListener {
if (SystemClock.elapsedRealtime() - lastClickTime < 600L)
return@setOnClickListener
lastClickTime = SystemClock.elapsedRealtime()
action()
}
}
它还可以防止同时点击应用的各个部分。
答案 37 :(得分:0)
将按钮设置为可单击是一次正确的方法,即在单击时将false设置为false,然后在希望再次使按钮可单击时将其设置为true。例如,请考虑以下情形:单击按钮进行服务调用,完成服务后,您要显示一个对话框。为此,单击按钮后,您可以设置setClickable(false),一旦服务响应,您将通过传递给自定义对话框的引用来执行setClicklable(true)。当对话框调用isShowing()时,您可以触发侦听器和setClicklable(true)。
答案 38 :(得分: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
答案 39 :(得分:0)
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()
}
答案 40 :(得分: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()}"
... />
答案 41 :(得分: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;
}
答案 42 :(得分:0)
如果单击该按钮,您将打开一个新片段,只需将myMap.get("myObject1");
添加到正在打开的新片段的根视图中。
答案 43 :(得分: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;
}
}
答案 44 :(得分:0)
阻止UI线程时,单击事件排队。在按钮单击事件上,请尽快更改为后台任务,以避免点击事件排在彼此后面。
在activity类中声明一个volatile布尔值或锁:
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;
}
}
答案 45 :(得分:0)
我需要用片段进行woking,只需要设置一个标志来控制点击:我只想要第一个,其他人无法访问监听器
private boolean flag = true;
...
@Override
public void onClick(View view) {
...
if (flag) {
...
listener.onFragmentInteraction(Constants.MY_FRAGMENT, bundle);
flag = false;
}
...
}
希望它有用,如果不正确则纠正我
答案 46 :(得分:0)
只需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 即可。添加一行以避免多次单击。
@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
}
}
答案 47 :(得分: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);
}
答案 48 :(得分:0)
如果按钮唯一做的就是启动新活动,问题可以通过&#34; singleTop&#34;来解决。激活启动模式,并在意图上设置FLAG_ACTIVITY_CLEAR_TOP。这个在复杂活动的层次结构中不起作用,但对于简单的树状应用程序结构是可行的。
答案 49 :(得分: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;
}
}
答案 50 :(得分:0)
如果您不想(或不能)使用boolean
标记或覆盖onClickListener
,您还可以尝试在AndroidManifest.xml中使用android:launchMode="singleTop"
声明您的活动。
答案 51 :(得分:-3)
更优选的解决方案是,
onclick(){
btn.setEnabled(false);
btn.setClickable(false);
//yourwork
myWork();
}
myWork(){
//your tasks.
btn.setEnabled(true);
btn.setClickable(true);
}
由于链接可以轻易忽略,我不得不一次又一次地重复这个