20

一个按钮触发一个只应该被调用一次的动作。在执行操作之前,该按钮被禁用并隐藏在 onClick 处理程序中:

someButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        someButton.setEnabled(false);
        someButton.setClickable(false);
        someButton.setVisibility(View.GONE);
        performTaskOnce();
        }
    });

private void performTaskOnce() {
    Log.i("myapp", "Performing task");
    //Do something nontrivial that takes a few ms (like changing the view hierarchy)
}

即使按钮立即被禁用,仍然可以通过快速点击多次来触发多个“onClick”事件。(即被performTaskOnce多次调用)。似乎 onClick 事件在按钮实际被禁用之前排队。

我可以通过检查每个单独的 onClick 句柄是否已禁用相应的按钮来解决问题,但这似乎是一个 hack。有没有更好的方法来避免这个问题?

该问题出现在 Android 2.3.6 上,我无法在 Android 4.0.3 上重现它。但鉴于 4.x 设备的稀有性,排除旧设备不是一个选项。

4

5 回答 5

8

您可以在单击按钮时将布尔变量设置为 true,并在处理完单击后将其设置为 false。

通过这种方式,您可以忽略多次单击,而不必禁用按钮,从而避免烦人的按钮闪烁。

boolean processClick=true;
someButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        if(processClick)
         {
        someButton.setEnabled(false);
        someButton.setClickable(false);
        someButton.setVisibility(View.GONE);
        performTaskOnce();
         }
        processClick=false; 
        }
    });

private void performTaskOnce() {
    Log.i("myapp", "Performing task");
    //Do something nontrivial that takes a few ms (like changing the view hierarchy)
}
于 2012-06-01T12:43:04.490 回答
6

为了保持DRY

// Implementation
public abstract class OneShotClickListener implements View.OnClickListener {
    private boolean hasClicked;

    @Override public final void onClick(View v) {
        if (!hasClicked) {
            onClicked(v);
            hasClicked = true;
        }
    }

    public abstract void onClicked(View v);
}

// Usage example
public class MyActivity extends Activity {
    private View myView;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        myView.setOnClickListener(new OneShotClickListener() {
            @Override public void onClicked(View v) {
                // do clicky stuff
            }
        });
    }
}
于 2014-03-13T18:46:21.447 回答
1

有点晚了,但这可能对某人有用。就我而言,我这样称呼另一项活动;

声明一个布尔值;

boolean clickable;

在点击监听器中;

if(clickable){
   // Launch other activity
   clickable = false;
}

调用 onResume 时启用;

@Override
public void onResume() {
    Log.e(TAG, "onResume");
    super.onResume();
    clickable = true;
}
于 2014-03-24T07:19:22.083 回答
0

您可以使用RxView( com.jakewharton.rxbinding2.view.RxView) 是由 Jake Wharton 创建的围绕 RxJava 的扩展。

要将其集成到项目中,您应该使用implementation 'com.jakewharton.rxbinding3:rxbinding:3.1.0'

简单的Java用法:

RxView.clicks(yourButton)
    .sample(500, TimeUnit.MILLISECONDS)
    .subscribe { action() }

Kotlin您可以创建扩展功能来处理您的点击:

View.singleClick(action: () -> Any) {
    RxView.clicks(this)
        .sample(500, TimeUnit.MILLISECONDS)
        .subscribe { action() }
}

样本:

科特林

yourButton.singleClick({
    //do some stuff here
})

爪哇

SingleClickListenerKt.singleClick(yourButton, () -> {
    doSomeStuff();
    return null;
    });

注意:如果您愿意,您可以使用任何 RxJava 运算符debounce, map, first,例如 等。

于 2020-03-21T12:06:07.807 回答
-1

声明一个变量并将其用作

 boolean boo = false;
 someButton.setOnClickListener(new OnClickListener() {
 @Override
 public void onClick(View v) {
 if(boo==false){
    someButton.setEnabled(false);
    someButton.setClickable(false);
    someButton.setVisibility(View.GONE);
    boo = true;
 }


    }
});

这样你就可以防止多次点击你的按钮

希望有帮助

于 2012-06-01T10:07:29.580 回答