• 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

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

     

     

     

     

     

  • 相关阅读:
    第六章 函数、谓词、CASE表达式 6-3 CASE表达式
    第六章 函数、谓词、CASE表达式 6-2 谓词
    第六章 函数、谓词、CASE表达式 6-1 各种各样的函数
    第五章 复杂查询 5-3 关联子查询
    第五章 复杂查询 5-2 子查询
    第五章 复杂查询 5-1 视图
    第四章 数据更新 4-3 事务
    第四章 数据库和SQL 4-3 数据的更新(UPDATE语句的使用方法)
    面向对象进阶
    多态
  • 原文地址:https://www.cnblogs.com/StephenWu/p/6217234.html
Copyright © 2020-2023  润新知