【问题标题】:How can I be notified when a Snackbar has dismissed itself?当 Snackbar 自行关闭时,如何通知我?
【发布时间】:2015-09-04 17:49:06
【问题描述】:

我正在使用来自 com.android.support:design:22.2.0 库的 Snackbar。我用它来撤消删除。为了让我的生活更轻松,我将让 UI 看起来像是实际从数据源中删除了东西,如果没有按下快餐栏中的撤消按钮,则实际执行从数据源中删除的操作。所以,我想知道什么时候 Snackbar 不再可见,所以删除这些项目是安全的。

我可以在 Snackbar 上调用 getView(),但我不确定我应该使用哪个监听器。我试过setOnSystemUiVisibilityChangeListener(),但没用,我相信它只适用于系统状态栏。

此外,Snackbar 不能扩展,因为它有一个私有构造函数。

【问题讨论】:

  • 此功能将在下一版本的支持设计库中提供

标签: android material-design android-design-library android-snackbar snackbar


【解决方案1】:

Google 设计库在版本 23 中支持 Snackbar 回调。请参阅 Snackbar docsCallback docs。 然后,当 Snackbar 被关闭时(以及显示时)以及关闭类型(如果这对您有用),您将收到通知:

snackbar.addCallback(new Snackbar.Callback() {

    @Override
    public void onDismissed(Snackbar snackbar, int event) {
      //see Snackbar.Callback docs for event details
      ...  
    }

    @Override
    public void onShown(Snackbar snackbar) {
       ...
    }
  });

【讨论】:

  • setCallback() 现在已弃用。使用 addCallback() 代替
【解决方案2】:
snackbar.addCallback(new Snackbar.Callback() {

    @Override
    public void onDismissed(Snackbar snackbar, int event) {
        if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) {
            // Snackbar closed on its own
        }
    }

    @Override
    public void onShown(Snackbar snackbar) {
        ...
    }
});

【讨论】:

  • 很高兴提及该事件,因为单击 actionText 时也会调用 onDismissed
  • 在大多数情况下,最好检查if (event != Snackbar.Callback.DISMISS_EVENT_ACTION),否则如果用户手动关闭或另一个连续的小吃店关闭了小吃店,您的关闭逻辑将不会运行。
  • 感谢此行event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT
【解决方案3】:

kotlin 中的 Snackbar.addCallback

val snackBar = Snackbar
                .make(view, "Text Snackbar", Snackbar.LENGTH_LONG)
                .addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
                    override fun onShown(transientBottomBar: Snackbar?) {
                        super.onShown(transientBottomBar)
                    }

                    override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
                        super.onDismissed(transientBottomBar, event)
                    }
                })

        val snackBarView = snackBar.view
        snackBarView.setBackgroundColor(Color.RED)
        snackBar.show()

【讨论】:

  • 厉害了,一直在找kotlin版本
【解决方案4】:

最近我自己在滚动和显示 Snackback 时偶然发现了这个问题,在第一个甚至消失之前就显示了太多。我必须想办法知道应用程序是否应该放置 Snackbar。

我个人找到了这个解决方案。

确实,Snackbar 本身并没有提供任何类型的监听器来获取状态/可见性,但是您仍然可以从 Snackbar 中获取 View 对象( getView(); )。在 View Object 中,您有机会使用多种方法来添加侦听器。

要实现它,您必须摆脱常见的“一体式”Toast/Snackbar 用法,因为添加侦听器会返回 void

我个人发现 OnAttachStateChangeListener 可以满足我的需求。

在我的代码中添加一个sniper,以防它对你有用。

Snackbar snack = Snackbar.make(getView(), "My Placeholder Text", Snackbar.LENGTH_LONG);

snack.getView().addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
    @Override
        public void onViewAttachedToWindow(View v) {
            canDisplaySnackbar = false;
        }

    @Override
    public void onViewDetachedFromWindow(View v) {

        Handler h = new Handler();
        h.postDelayed(new Runnable() {
            @Override
            public void run() {
                canDisplaySnackbar = true;

                }
        }, 1000);
    }
});
snack.show();

请注意,这只是我自己的问题的实现,带有 postDelayed Runnable 的 Handler 甚至可能不适合您的情况。这只是为了大致了解我建议使用我已经拥有的 sn-p 的实现。

【讨论】:

  • and_dev 的 andswer 现在是更好的答案。
【解决方案5】:

要在显示或关闭小吃店时收到通知,您可以通过 setCallback(Callback) 提供 Snackbar.Callback。

【讨论】:

  • setCallBack 现已弃用,请改用 addCallBack
【解决方案6】:

onDismissed 在点击动作文本时也会被调用,因为这个原因需要放置一个条件,例如

event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT

现在新代码如下所示。

final Snackbar snackBar = Snackbar.make(findViewById(R.id.root_layout), result, Snackbar.LENGTH_LONG);

snackbar.addCallback(new Snackbar.Callback() {

@Override
public void onDismissed(Snackbar snackbar, int event) {
 if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) {
        // Snackbar closed on its own
    }  
}

@Override
public void onShown(Snackbar snackbar) {
...
}
});
snackBar.show();

【讨论】:

  • 不鼓励仅使用代码回答,因为它们没有为未来的读者提供太多信息,请对您所写的内容提供一些解释
  • 在大多数情况下,最好检查if (event != Snackbar.Callback.DISMISS_EVENT_ACTION),否则如果用户手动关闭或另一个连续的小吃店关闭小吃店,您的关闭逻辑将不会运行。
【解决方案7】:
【解决方案8】:

在 Kotlin 中,这对我有用:

Snackbar.make(
    binding.root,
    getString(R.string.ticket_posted),
    LENGTH_LONG)
    .setAction(getString(R.string.undo)) {
        Log.d(TAG, "Try to undo ticket $key")
    }
    .addCallback(object : BaseCallback<Snackbar>() {
        override fun onDismissed(
            transientBottomBar: Snackbar?,
            event: Int
        ) {
            super.onDismissed(transientBottomBar, event)
            if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) {
                Log.d(TAG, "Try to reset")
            }
        }
    })
    .show()
}

【讨论】:

    【解决方案9】:

    目前无法在 Snackbar 完成显示时收到通知。

    在此线程中,讨论了一种基于 Snackbar 显示持续时间的计时器的解决方法。 Snackbar in Support Library doesn't include OnDismissListener()?

    使用此解决方法需要考虑的一个问题是 Snackbar 持续时间可能会重新启动。 material design specification for Snackbar 表示如果显示不相关的对话框或弹出窗口,就会发生这种情况。

    【讨论】:

      【解决方案10】:

      感谢 Kotlin 中的@SergeyMilakov,它是:

      @SuppressLint("WrongConstant") // Suppress an error when set duration.
      private fun showSnackbar() {
          val DURATION = 5000
      
          Snackbar.make(view!!, "Remove item?"), DURATION).apply {
              setAction("Undo") {
                  // Your action when a button is clicked.
              }
              addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
                  /* override fun onShown(transientBottomBar: Snackbar?) {
                      super.onShown(transientBottomBar)
                      Timber.d("*** onShown")
                  }*/
      
                  override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
                      super.onDismissed(transientBottomBar, event)
                      if (event != Snackbar.Callback.DISMISS_EVENT_ACTION) {
                          // Your action when the Snackbar is closed and the button was not clicked.
                      }
      
                  }
              })
              view.setBackgroundColor(ContextCompat.getColor(context, R.color.black))
              setActionTextColor(ContextCompat.getColor(context, R.color.yellow))
              show()
          }
      }
      

      请注意,Snackbar 会显示,即使您移动到其他屏幕(例如,返回)。所以,不要忘记检查您是否在正确的屏幕上进行操作。

      另外Snackbar 在屏幕旋转后也不会恢复。

      【讨论】:

        【解决方案11】:

        目前你无法实现。

        关闭小吃店时不会调用侦听器。

        最简单的方法是将记录临时保存在别处(甚至是局部变量),然后如果碰巧点击了撤消按钮,则重新插入。

        【讨论】:

          【解决方案12】:
              snackbar.addCallback(new Snackbar.Callback() {
                  public void onShown(Snackbar snackbar) {
                     //  on show  
                  }
           public void onDismissed(Snackbar snackbar, int event) {
                    //  on dismiss  
                  }
                });
          

          【讨论】:

          • 请在您的代码 sn-p 旁边提供描述/解释。
          【解决方案13】:

          我和你的问题完全一样。我的解决方案是……

                        final Snackbar povrati_obrisani_unos = Snackbar.make (coordinatorLayout, "Ponisti brisanje", Snackbar.LENGTH_INDEFINITE)
                              .addCallback (new Snackbar.Callback (){
                                  @Override
                                  public void onDismissed(Snackbar transientBottomBar, int event) {
                                      super.onDismissed (transientBottomBar, event);
                                      if(event==DISMISS_EVENT_SWIPE){//here we detect if snackbar is swipped away and not cliked (which is undo in my case)
                                          Uri uriDelete = Uri.parse (obrisano.getImageuri ());
                                          ContentResolver contentResolver = getContentResolver();
                                          contentResolver.delete (uriDelete, null, null);
                                          Toast.makeText (MainActivity.this,
                                                  "Ocitavanje i slika su trajno obrisani", Toast.LENGTH_SHORT).show ();
                                      }
          

          就是这样,不想复制粘贴snackbar.action 这是撤消。想在这里尽可能清楚。

          问候内纳德

          【讨论】:

            猜你喜欢
            • 2016-04-30
            • 2019-09-01
            • 1970-01-01
            • 1970-01-01
            • 2018-08-31
            • 2016-04-07
            • 2015-07-07
            • 2016-07-06
            • 2019-11-20
            相关资源
            最近更新 更多