Android Material Design 系列之 SnackBar详解

Posted shaotine

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Material Design 系列之 SnackBar详解相关的知识,希望对你有一定的参考价值。

SnackBar是google Material Design提供的一种轻量级反馈组件。支持从布局的底部显示一个简洁的提示信息,支持手动滑动取消操作,同时在同一个时间内只能显示一个SnackBar.

 

Snackbar是如何实现的呢?我们主要讨论Snackbar的显示逻辑,包括:延迟消失和同一时间只支持一个Snackbar显示

首先我们先看下Snackbar用到的两个类

其中SnackbarManager是个单例,利用单例的形式来保证每次只会显示一个Snackbar。

 

Snackbar中的sHandler用于SnackbarManager.Callback回调函数中,每个Snackbar都会去实现SnackbarManager.Callback的回调,包括show和dimiss两个方法。SnackbarManager也是通过这个回调来区分每个不同的Snackbar

private boolean isCurrentSnackbarLocked(ConvinentSnackbarManager.Callback callback) {
    return mCurrentSnackbar != null && mCurrentSnackbar.isSnackbar(callback);
}

  

为了方便用户能够对Snackbar的行为进行自定义操作,Snackbar提供了 Snackbar.Callback,包括了Snackbar显示,消失后的行为。用户可以根据自己的业务需求,设置这个callback.具体提供的接口方法如下:

/**
         * Called when the given {@link ConvinentSnackbar} has been dismissed, either through a time-out,
         * having been manually dismissed, or an action being clicked.
         *
         * @param snackbar The snackbar which has been dismissed.
         * @param event    The event which caused the dismissal. One of either:
         *                 {@link #DISMISS_EVENT_SWIPE}, {@link #DISMISS_EVENT_ACTION},
         *                 {@link #DISMISS_EVENT_TIMEOUT}, {@link #DISMISS_EVENT_MANUAL} or
         *                 {@link #DISMISS_EVENT_CONSECUTIVE}.
         * @see ConvinentSnackbar#dismiss()
         */
        public void onDismissed(ConvinentSnackbar snackbar, @ConvinentSnackbar.Callback.DismissEvent int event) {
            // empty
        }

        /**
         * Called when the given {@link ConvinentSnackbar} is visible.
         *
         * @param snackbar The snackbar which is now visible.
         * @see ConvinentSnackbar#show()
         */
        public void onShown(ConvinentSnackbar snackbar) {
            // empty
        }

  

SnackbarManager中,为了保存每个一个Snackbar,提供了SnackBarRecord的内部类,这个类有两个成员变量,一个是Snackbar的callback,一个是这个Snackbar的duration。但是SnackBarManager不是用一个队列去保存每一个新生成的不同的Snackbar。只会保存当前和一下要显示的。而下一个的规则是:在一个Snackbar的显示周期中(已经有一个Snackbar存在的情况下),只会把最后一个新的Snackbar作为下一个Snackbar。假如你每点击一次按钮都会新生成一个Snackbar,那么在2.75s(LONG_DURATION_MS)内,你点击了N次,SnackBarManager只会显示1次和第N次。其它的都不会显示。并且第N次的显示是在第一次显示结束后会自动调用显示

public void show(int duration, ConvinentSnackbarManager.Callback callback) {
        synchronized (mLock) {
            if (isCurrentSnackbarLocked(callback)) {
                // Means that the callback is already in the queue. We\'ll just update the duration
                mCurrentSnackbar.duration = duration;

                // If this is the ConvinentSnackbar currently being shown, call re-schedule it\'s
                // timeout
                mHandler.removeCallbacksAndMessages(mCurrentSnackbar);
                scheduleTimeoutLocked(mCurrentSnackbar);
                return;
            } else if (isNextSnackbarLocked(callback)) {
                // We\'ll just update the duration
                mNextSnackbar.duration = duration;
            } else {
                // Else, we need to create a new record and queue it
                mNextSnackbar = new ConvinentSnackbarManager.SnackbarRecord(duration, callback);
            }

            if (mCurrentSnackbar != null && cancelSnackbarLocked(mCurrentSnackbar,
                    ConvinentSnackbar.Callback.DISMISS_EVENT_CONSECUTIVE)) {
                // If we currently have a ConvinentSnackbar, try and cancel it and wait in line
                return;
            } else {
                // Clear out the current snackbar
                mCurrentSnackbar = null;
                // Otherwise, just show it now
                showNextSnackbarLocked();
            }
        }
    }

  

SnackbarManager里也有一个Handler,这个Handler是用于延迟消失动画的。每次生成一个SnackBar,如果duration不是设置为LENGTH_INDEFINITE(不消失),SnackbarManager在显示之后,都会用这个Handler的sendMessageDelayed

 来进行延迟发送一个消失消息。Handler在收到这个消息后,会调用SnackbarManager.Callback 

,通过SnackbarManager的Callback来实现Snackbar的显示和消失。

 

Snackbar的优点:

 提供了比Toast更灵活和更友好的显示方法。

 

Snackbar的优点:

1.显示位置过于单一,现在目前只支持底部显示。

2.滑动操作过于单一,现在只支持从左向右滑动取消。

 

对Snackbar进行了些改动,github的项目为ConvinentSnackbar。地址为:

https://github.com/stephen-wu-yuan/ConvinentSnackbar

改组件支持设置滑动方向和支持顶部显示。

 

 

 

 

 

 

以上是关于Android Material Design 系列之 SnackBar详解的主要内容,如果未能解决你的问题,请参考以下文章

android material design

Android Material Design 布局示例

xml Android Material Design Colors

xml Android Material Design Colors

xml Android Material Design Colors

xml Android Material Design Colors