Android:阻止按钮上的多个onClick事件(已被禁用)

rlu*_*uba 19 java user-interface android

按钮触发仅应调用一次的操作.在执行操作之前,该按钮被禁用并隐藏在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)
}
Run Code Online (Sandbox Code Playgroud)

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

我可以通过检查每个onClick手柄来解决问题,相应的按钮是否已被禁用,但这似乎是一个黑客攻击.有没有更好的方法来避免这个问题?

问题出现在Android 2.3.6上,我无法在Android 4.0.3上重现它.但鉴于4.x设备的稀有性,不能排除旧设备.

Vip*_*hah 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)
}
Run Code Online (Sandbox Code Playgroud)

  • 这似乎最简单.在iOS中,UIApplication类有一个'beginIgnoringInteractionEvents'消息,可以在全局范围内执行此操作.这有时候会很好.但是,我找不到Android的等价物.你也可以使用一个简单的守护"if(!processClick)return;".这样可以减少嵌套量. (3认同)

Chr*_*rry 5

为了保持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
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)