Android Material Design 系列之 SnackBar详解

春衣少年当酒歌,起舞四顾以笑和。这篇文章主要讲述Android Material Design 系列之 SnackBar详解相关的知识,希望能为你提供帮助。
SnackBar是google Material Design提供的一种轻量级反馈组件。支持从布局的底部显示一个简洁的提示信息,支持手动滑动取消操作,同时在同一个时间内只能显示一个SnackBar.
 
那Snackbar是如何实现的呢?我们主要讨论Snackbar的显示逻辑,包括:延迟消失和同一时间只支持一个Snackbar显示
首先我们先看下Snackbar用到的两个类

Android Material Design 系列之 SnackBar详解

文章图片

p.p1 { margin: 0; font: 12px "PingFang SC"; color: rgba(69, 69, 69, 1) } p.p2 { margin: 0; font: 12px Helvetica; color: rgba(69, 69, 69, 1); min-height: 14px } p.p3 { margin: 0; font: 12px Helvetica; color: rgba(69, 69, 69, 1) } span.s1 { font: 12px Helvetica } span.s2 { font: 12px "PingFang SC" }其中SnackbarManager是个单例,利用单例的形式来保证每次只会显示一个Snackbar。
 
【Android Material Design 系列之 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; font: 12px "PingFang SC"; color: rgba(69, 69, 69, 1) } span.s1 { font: 12px 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 eventThe 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; font: 12px "PingFang SC"; color: rgba(69, 69, 69, 1) } span.s1 { font: 12px 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; font: 12px Helvetica; color: rgba(69, 69, 69, 1) } span.s1 { font: 12px "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
改组件支持设置滑动方向和支持顶部显示。
 
 
 
 
 
 

    推荐阅读