【问题标题】:How to prevent double code running by clicking twice fast to a button in Android如何通过在Android中快速单击两次按钮来防止双重代码运行
【发布时间】:2012-07-02 09:00:27
【问题描述】:

如果我在我的 Android 应用程序中快速单击按钮,它背后的代码似乎会运行两次。 如果我单击菜单按钮两次,则必须启动 onclick 的活动只会启动两次,我必须退出两次。

这真的很烦人,因为如果我点击菜单按钮的速度太快,我可以在后台加载一大堆活动,我必须一个一个地退出它们,所以这显然是我想要的应用程序的错误状态解决这个问题。

这个问题我该怎么办?

我使用简单的 onClickListeners 和 Buttons

编辑:

关于答案和 cmets,我的菜单按钮如下所示:

top20Button.setOnClickListener(new OnClickListener()
{
    public void onClick(View v)
    {
        favButton.setClickable(false);
        nearButton.setClickable(false);
        highlightedButton.setClickable(false);
        top20Button.setClickable(false);

        Intent i = new Intent();
        i.putExtra("showDialog", false);
        i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        i.setClass(Search.this, Top20.class);
        startActivity(i);
        finish();

    }
});

经过所有这些更正后,它仍然是一样的:S 当我像疯子一样点击时,历史堆栈上有多个活动,我必须退出多次。

有什么建议吗?我做错了什么?

【问题讨论】:

  • 尝试禁用点击按钮。所以当它首先被点击时,它会被禁用并且不会捕获任何未来的点击,我猜。
  • 即使使用 SINGLE_TOP,堆栈上仍有多个活动?检查我的更新答案...

标签: android android-button


【解决方案1】:

您可以使用以下代码:btn.setEnabled(false);

btn.setOnclickListener(new View.onClickListener(){

      public void onClick(View v) {
            btn.setEnabled(false);

      }
});

【讨论】:

  • 但它会禁用进一步点击其他,然后你如何再次启用?
  • @Miguel:在上面的例子中,用 OnClickListener 编写的代码启动了一个活动,所以当用户回到之前的活动时,它会自动启用。但在其他情况下,例如在 onClickListener 中启动任何异步任务,那么 onPostExecute() 将是您再次启用按钮的最佳位置。
【解决方案2】:

您可以像这样暂时禁用视图

public static void disableTemporarly(final View view) {

        view.setEnabled(false);
        view.post(new Runnable() {
            @Override
            public void run() {

                view.setEnabled(true);
            }
        });
    }

编辑:

上述解决方案可以正常工作。 但是使用 Kotlin 的力量会变得更好

1) 创建 SafeClikc 监听器

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

2) 添加扩展功能使其适用于任何视图,这将创建一个新的 SafeClickListener 并将工作委托给它

fun View.setSafeOnClickListener(onSafeClick: (View) -> Unit) {

    val safeClickListener = SafeClickListener {
        onSafeClick(it)
    }
    setOnClickListener(safeClickListener)
}

3) 现在使用起来非常方便

settingsButton.setSafeOnClickListener {
    showSettingsScreen()
}

快乐的 Kotlin ;)

【讨论】:

  • 我使用了上述的变体来解决类似的问题。高效且有效的答案,没有其他方法的复杂性。
【解决方案3】:
 Button.setOnClickListener(new View.OnClickListener {  
   @Override
   public void onClick(final View v) {
        v.setEnabled(false);
        v.postDelayed(new Runnable() {
         @Override
         public void run() {
            v.setEnabled(true);
         }
        },150); //150 is in milliseconds
    }
 });  

【讨论】:

    【解决方案4】:

    嗯,这是预期的行为......

    使用 SINGLE_TOP 标志启动您的新活动

    或者尝试在您的 AndroidManifest.xml 中为 Top20 活动设置 android:launchMode="singleInstance"

    【讨论】:

    • 如果我添加这个语句,一个奇怪的动画会出现在活动变化中:布局向左移动出现一个空白屏幕,然后显示我的新活动。由于某种原因,此设置会跳过我当前的所有活动动画: overridePendingTransition(0, 0);如果你能告诉我如何禁用这个空白屏幕动画,我可以选择你的答案作为我的问题的答案,因为现在我没有重复的活动。 =)
    • 尝试在启动活动时添加 NO_ANIMATION 标志 :)
    【解决方案5】:

    这样解决了activity的多个Instances的问题,并且仍然播放默认动画

    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    

    【讨论】:

      【解决方案6】:

      此解决方案更符合我的要求。而是使用启用/禁用视图功能。我使用时间,首先,创建一个变量来存储用户最后一次按下视图*,然后当用户按下视图时,捕获变量中的时间,以便比较当前时刻和用户最后一次按下视图,如果时间之间的差异时间太小,这意味着快,或者非常快,请忽略它,仅此而已。但是,如果它对您来说是一个合理的时间,请将 last time 变量设置为当前时间,然后做任何您想做的事情。

      @Override
      public void onListItemClick(ListView list, View item, int position, long id) {
      
          Long now = System.currentTimeMillis();
          if((now - lastTimeSelected) > 500){
              lastTimeSelected = now;
              // your code goes here
          } else {
              Log.i(TAG, "Too fast!");
          }
      
      }
      

      我在其他帖子上看到了类似的answer,但似乎没有人喜欢这种方法。

      【讨论】:

        【解决方案7】:

        将以下代码片段添加到 Androidmanifest.xml 中的 Activity 定义中

        android:launchMode = "singleTask"
        

        【讨论】:

          【解决方案8】:

          Application 类中使用frozen 变量。

          那是

          public class App extends Application {
          public static boolean frozen = false;
          }
          

          点击时某处:

          //...
          onClick() {
          if (frozen) {
          return;
          }
          frozen = true
          }
          //...
          

          在某个地方发布,例如,当新的 Activity 启动时

          onCreate (...) {
          super.onCreate(...);
          frozen = false;
          }
          

          AndroidManifest.xml:

          <application
                  android:allowBackup="true"
                  android:largeHeap="true"
                  android:name="com.example.App"
                  android:icon="@drawable/icon"
                  android:label="@string/app_alias"
                  android:theme="@style/AppTheme" >
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-02
            • 1970-01-01
            • 2021-02-18
            • 2015-02-25
            • 2022-01-21
            • 2016-02-12
            相关资源
            最近更新 更多