Android Material Design 系列之 SnackBar详解

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

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

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

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "PingFang SC"; color: #454545 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #454545; min-height: 14.0px }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #454545 }
span.s1 { font: 12.0px Helvetica }
span.s2 { font: 12.0px "PingFang SC" }

其中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);
}

  

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "PingFang SC"; color: #454545 }
span.s1 { font: 12.0px Helvetica }

为了方便用户能够对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
        }

  

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "PingFang SC"; color: #454545 }
span.s1 { font: 12.0px Helvetica }

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

  

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #454545 }
span.s1 { font: 12.0px "PingFang SC" }

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

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

时间: 2024-11-22 18:01:40

Android Material Design 系列之 SnackBar详解的相关文章

Android Material Design系列之主题样式介绍说明

今天这篇文章应该算是Material Design系列的补充篇,因为这篇文章本来应该放到前面讲的,因为讲的是主题嘛,对于一些状态和颜色的介绍,因为我们一新建一个项目时,系统自带了三个属性的颜色,现在就重点介绍这三个颜色属性的意义和作用.讲明白这个,留着以后讲别的用. 最常用的三个颜色属性 colorPrimary colorPrimaryDark colorAccent 这三个分别代表什么意思呢? colorPrimaryDark 是状态栏底色 colorPrimary 如果你不手动自己去修改t

有关Material Design新特性的详解。

源码地址:https://github.com/chrisbanes/cheesesquare 自己添加备注后的地址:https://github.com/heinika/DrawerLayoutDemo 英文教程:https://guides.codepath.com/android/Handling-Scrolls-with-CoordinatorLayout 中文教程:http://my.oschina.net/kooeasy/blog/484593 主要包含: DrawerLayout

Android Material Design系列之RecyclerView和CardView

去年很早之前,我就讲解过RecyclerView的使用,今天我们就在讲解CardView的时候,顺便再把RecyclerView同时讲解一下.RecyclerView.CardView为用于显示复杂视图的新增Widget.接下来看看如何使用吧. RecyclerView RecyclerView介绍 RecyclerView作为替代ListView使用,它更先进,更灵活,RecyclerView标准化了ViewHolder,ListView中convertView是复用的,在RecyclerVi

Android Design Support Library使用详解

Android Design Support Library使用详解 Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个support库里面,Google给我们提供了更加规范的MD设计风格的控件.最重要的是,Android Design Support Library的兼容性更广,直接可以向下兼容到Android 2.2.这不得不说是一个良心之作. 使用S

Android系列之Android 命令行手动编译打包详解

http://www.qdmm.com/BookReader/1222701,54263720.aspxhttp://www.qdmm.com/BookReader/1222701,54263869.aspxhttp://www.qdmm.com/BookReader/1222701,54263871.aspxhttp://www.qdmm.com/BookReader/1222701,54263876.aspxhttp://www.qdmm.com/BookReader/1222701,542

Android组件系列----Activity组件详解

[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3924567.html 联系方式:[email protected] [正文] 注:四大组件指的是应用组件:Activity.Service.BroadcastReceiver.ContentProvider:之前的控件指的是UI组件. 博文目录: 一.Activity简介 二.Activity的状

Android自定义控件系列八:详解onMeasure()(二)--利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题

上一篇文章详细讲解了一下onMeasure/measure方法在Android自定义控件时的原理和作用,参看博文:Android自定义控件系列七:详解onMeasure()方法中如何测量一个控件尺寸(一),今天就来真正实践一下,让这两个方法大显神威来帮我们搞定图片的屏幕适配问题. 请尊重原创劳动成果,转载请注明出处:http://blog.csdn.net/cyp331203/article/details/45038329,非允许请勿用于商业或盈利用途,违者必究. 使用ImageView会遇到

Android Material Design 兼容库的使用

Android Material Design 兼容库的使用 mecury 前言:近来学习了Android Material Design 兼容库,为了把这个弄懂,才有了这篇博客,这里先推荐两篇博客:1.Android Material Design 兼容库的使用详解2.Android应用Design Support Library完全使用实例第一篇博客是这个兼容库的详细解析,我参考了里面的许多内容,第二篇是兼容库的大致介绍,如果你能把这两篇全部弄懂,我这篇也没有必要看了.说了这么多,开始正文吧

Material Design系列,自定义Behavior支持所有View

Material Design系列,自定义Behavior支持所有View 版权声明:转载必须注明本文转自严振杰的博客: http://blog.csdn.net/yanzhenjie1003 友情连接: Material Design博客专栏 系列博客: 1. Material Design系列,Behavior之BottomSheetBehavior与BottomSheetDialog 2. Material Design系列,Behavior之SwipeDismissBehavior 3.