2010-05-22 108 views
10

我有一个带有OnClickListener的按钮。为了说明的目的,考虑一个按钮,显示模态对话框:处理按钮上的快速点击

public class SomeActivity ... { 

    protected void onCreate(Bundle state) { 
    super.onCreate(state); 

    findViewById(R.id.ok_button).setOnClickListener(
     new View.OnClickListener() { 
     public void onClick(View v) { 
      // This should block input 
      new AlertDialog.Builder(SomeActivity.this) 
      .setCancelable(true) 
      .show(); 
     } 
    }); 
} 

正常使用情况下,将显示警告对话框和块进一步输入。用户必须关闭对话框才能再次点击该按钮。

但是在对话框出现之前,有时会调用按钮的OnClickListener两次。您可以通过点击按钮非常快速地复制它。我通常必须在发生之前尝试多次,但迟早我会在对话框阻止输入之前触发多个onClick(...)调用。

我在Motorola Droid手机上的Android 2.1中看到了这种行为。我们在市场上收到了4次崩溃报告,表明偶尔会发生这种情况。

这取决于我们的OnClickListeners做什么,这会导致各种各样的混乱。我们如何确保阻止对话在第一次敲击后实际上阻止输入?

+0

您是否尝试在onClick()外部创建AlertDialog,并在onClick()中调用show()? – jfpoilpret 2010-05-22 00:42:50

回答

17

Romain Guy证实这确实是Android中的一个错误:“只有当用户在< 125ms内按下按钮两次时才会发生,我相信我们在Froyo修复了这个可能的错误。

我们将使用“玻璃窗格”模式来解决旧操作系统上的错误。也就是说,我们将以不可见的视角覆盖屏幕。在第一次点击事件之后,我们将使视图“可见”,以便拦截后续的触摸事件。

仅防止一个按钮上的事件是不够的。您需要阻止整个活动的所有后续活动,直到对话被解除,活动恢复等等,此时您再次使玻璃窗格“不可见”。

如果这不起作用,我们只需要忍受这一点,并更好地容忍意外的额外事件。

+0

哇...你是鲍勃李? – 2010-05-23 22:27:01

+0

我想这取决于谁是“鲍勃李”。 :-)我不认识Bob Lee的其他程序员。 :-) – 2010-05-24 17:59:09

+1

鲍勃和我正在做一些与鲍勃上面描述的非常相似的东西。主要的区别是我们的“玻璃窗格”不是实际的视图。相反,我们所有的活动都扩展了一个共同的基础活动,并且我们所有的对话都扩展了一个基础对话框。由于我们有这些基类,我们可以在每个基类中引入一个布尔标志。该标志表示我们是否接受或阻止输入。 在每个这些基类中,我们重写dispatchTouchEvent。根据国旗,我们可以简单地返回真实,拦截和阻止事件。这种方法似乎有效。 – 2010-05-25 14:22:38

9

感谢您试用mdma,但这是一个平台问题,而不是我们的代码问题。更糟糕的是,这显然不是一个可以在用户代码中解决的问题(它需要来自触摸屏驱动程序的未传递的细节)。此外,你的代码示例不会做你认为它的作用。 show()不会立即显示对话框。它在事件队列的最后添加一条消息,最终显示对话框。在onClick()返回后,更多的触摸事件可能已经在队列中等待执行。

我不确定为什么人们投票答案。

+0

嗨,我删除了我的答案。但我不知道如何确定您是否处于两州之间 - 在处理点击和显示对话之间,然后忽略进一步的点击之间不可能。 – mdma 2010-05-25 14:46:40