当Snackbar解散自己时如何通知我?

时间:2015-06-18 21:49:15

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

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

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

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

13 个答案:

答案 0 :(得分:137)

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) {
       ...
    }
  });

答案 1 :(得分:26)

    snackbar.setCallback(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) {
            ...
        }
    });

答案 2 :(得分:15)

最近我偶然发现了这个问题,当滚动和显示Snackback时,在第一个消失之前显示了太多。我必须找到一种方法来知道应用程序是否应该放置Snackbar。

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

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

要实现它,你必须走出常见的“一体化”Toast / Snackbar用法,因为添加监听器会返回 void

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

使用我的代码删除一个snipper,以防它对您有用。

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可能甚至不适合你的情况。这只是用我已经拥有的代码片段来概括我建议的实现。

答案 3 :(得分:12)

要在小吃栏显示或解除时收到通知,您可以通过setCallback(回拨)提供Snackbar.Callback。

答案 4 :(得分:4)

当单击动作文本时,也会调用

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();

答案 5 :(得分:4)

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

答案 6 :(得分:3)

当Snackbar完成显示时,目前无法获得通知。

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

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

答案 7 :(得分:3)

答案 8 :(得分:1)

目前你无法实现它。

当小吃店变得昏暗时,没有一个听众被叫。

最简单的方法是暂时将记录保存在其他位置(甚至是局部变量),然后在碰巧按下撤消按钮时重新插入。

答案 9 :(得分:1)

我有和你完全一样的问题。我的解决方法是...

              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,这是撤消操作。希望在这里尽可能清楚。

关于内纳德

答案 10 :(得分:0)

    snackbar.addCallback(new Snackbar.Callback() {
        public void onShown(Snackbar snackbar) {
           //  on show  
        }
 public void onDismissed(Snackbar snackbar, int event) {
          //  on dismiss  
        }
      });

答案 11 :(得分:0)

感谢科特林中的@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也不会在屏幕旋转后恢复。

答案 12 :(得分:0)

在 Kotlin 中,这对我有用:

.env