1. Snackbar类

Snackbar是5.0版本出现的控件,类似于Toast,显示在屏幕的底部,包含文字信息与一个可选的操作按钮。需要添加Design依赖库,并且使用Theme.AppCompat主题。

2. 创建Snackbar类

Snackbar利用静态方法make()来创建实例

public static Snackbar make(@NonNull View view, @StringRes int resId, @Duration int duration) {return make(view, view.getResources().getText(resId), duration);
}public static Snackbar make(@NonNull View view, @NonNull CharSequence text,@Duration int duration) {final ViewGroup parent = findSuitableParent(view);if (parent == null) {throw new IllegalArgumentException("No suitable parent found from the given view. "+ "Please provide a valid view.");}final LayoutInflater inflater = LayoutInflater.from(parent.getContext());final SnackbarContentLayout content =(SnackbarContentLayout) inflater.inflate(R.layout.design_layout_snackbar_include, parent, false);final Snackbar snackbar = new Snackbar(parent, content, content);snackbar.setText(text);snackbar.setDuration(duration);return snackbar;
}

创建Snackbar实例,需要寻找合适的父视图,优先选择CoordinatorLayout作为父视图。

private static ViewGroup findSuitableParent(View view) {ViewGroup fallback = null;do {if (view instanceof CoordinatorLayout) {// We've found a CoordinatorLayout, use itreturn (ViewGroup) view;} else if (view instanceof FrameLayout) {if (view.getId() == android.R.id.content) {// If we've hit the decor content view, then we didn't find a CoL in the// hierarchy, so use it.return (ViewGroup) view;} else {// It's not the content view but we'll use it as our fallbackfallback = (ViewGroup) view;}}if (view != null) {// Else, we will loop and crawl up the view hierarchy and try to find a parentfinal ViewParent parent = view.getParent();view = parent instanceof View ? (View) parent : null;}} while (view != null);// If we reach here then we didn't find a CoL or a suitable content view so we'll fallbackreturn fallback;
}

SnackbarContentLayout继承LinearLayout,并实现了BaseTransientBottomBar.ContentViewCallback,包含一个TextViewButton
design_layout_snackbar_include.xml文件,

<viewxmlns:android="http://schemas.android.com/apk/res/android"class="android.support.design.internal.SnackbarContentLayout"android:theme="@style/ThemeOverlay.AppCompat.Dark"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="bottom"><TextViewandroid:id="@+id/snackbar_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:paddingTop="@dimen/design_snackbar_padding_vertical"android:paddingBottom="@dimen/design_snackbar_padding_vertical"android:paddingLeft="@dimen/design_snackbar_padding_horizontal"android:paddingRight="@dimen/design_snackbar_padding_horizontal"android:textAppearance="@style/TextAppearance.Design.Snackbar.Message"android:maxLines="@integer/design_snackbar_text_max_lines"android:layout_gravity="center_vertical|left|start"android:ellipsize="end"android:textAlignment="viewStart"/><Buttonandroid:id="@+id/snackbar_action"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="@dimen/design_snackbar_extra_spacing_horizontal"android:layout_marginStart="@dimen/design_snackbar_extra_spacing_horizontal"android:layout_gravity="center_vertical|right|end"android:minWidth="48dp"android:visibility="gone"android:textColor="?attr/colorAccent"style="?attr/borderlessButtonStyle"/></view>

3. Snackbar设置

Snackbar可以设置文本和按钮

public Snackbar setText(@NonNull CharSequence message)
public Snackbar setText(@StringRes int resId)
public Snackbar setAction(@StringRes int resId, View.OnClickListener listener)
public Snackbar setAction(CharSequence text, final View.OnClickListener listener)
public Snackbar setActionTextColor(ColorStateList colors)
public Snackbar setActionTextColor(@ColorInt int color)

Snackbar可以监听视图

addCallback(new Snackbar.Callback(){@Overridepublic void onShown(Snackbar sb) {}@Overridepublic void onDismissed(Snackbar transientBottomBar, int event) {}
})

Dismissevent有下面五种情况

  • DISMISS_EVENT_SWIPE,向右滑动消失,只有父视图是CoordinatorLayout情况下才会发生
  • DISMISS_EVENT_ACTION,点击右侧按钮消失
  • DISMISS_EVENT_TIMEOUT,设置的显示时间到了消失
  • DISMISS_EVENT_MANUAL,调用Snackbardismiss方法消失
  • DISMISS_EVENT_CONSECUTIVE,新的Snackbar出现导致旧的消失

4. SnackbarManager类

SnackbarManager用来管理Snackbar控件的状态。
Snackbarshow()方法,会调用SnackbarManagershow(int, Callback)方法,而mManagerCallback会回调SnackbarshowView()hideView(int)方法。

static {sHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {@Overridepublic boolean handleMessage(Message message) {switch (message.what) {case MSG_SHOW:((BaseTransientBottomBar) message.obj).showView();return true;case MSG_DISMISS:((BaseTransientBottomBar) message.obj).hideView(message.arg1);return true;}return false;}});
}final SnackbarManager.Callback mManagerCallback = new SnackbarManager.Callback() {@Overridepublic void show() {sHandler.sendMessage(sHandler.obtainMessage(MSG_SHOW, BaseTransientBottomBar.this));}@Overridepublic void dismiss(int event) {sHandler.sendMessage(sHandler.obtainMessage(MSG_DISMISS, event, 0,BaseTransientBottomBar.this));}
};public void show() {SnackbarManager.getInstance().show(mDuration, mManagerCallback);
}

SnackbarManager内部包含两个记录mCurrentSnackbarmNextSnackbar。在SnackbarManagershow(int, Callback)方法中,

  • 查看是否是当前Snackbar,如果是,更新超时时间,结束。
  • 查看是否是NextSnackbar,如果是,更新数据,如果不是创建新的NextSnackbar
  • 取消当前Snackbar或者显示NextSnackbar

show(int, Callback)方法

public void show(int duration, Callback callback) {synchronized (mLock) {if (isCurrentSnackbarLocked(callback)) {// 如果是当前Snackbar,更新duration和超时提示mCurrentSnackbar.duration = duration;mHandler.removeCallbacksAndMessages(mCurrentSnackbar);scheduleTimeoutLocked(mCurrentSnackbar);return;} else if (isNextSnackbarLocked(callback)) {// 如果是NextSnackbar,更新durationmNextSnackbar.duration = duration;} else {// 否则就创建新的NextSnackbarmNextSnackbar = new SnackbarRecord(duration, callback);}if (mCurrentSnackbar != null && cancelSnackbarLocked(mCurrentSnackbar,Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE)) {// 如果当前Snackbar存在,取消显示当前Snackbar                return;} else {                mCurrentSnackbar = null;// 如果当前Snackbar不存在,显示NextSnackbarshowNextSnackbarLocked();}}
}// 取消显示当前Snackbar,调用callback的dismiss(DISMISS_EVENT_CONSECUTIVE)方法
private boolean cancelSnackbarLocked(SnackbarRecord record, int event) {final Callback callback = record.callback.get();if (callback != null) {// Make sure we remove any timeouts for the SnackbarRecordmHandler.removeCallbacksAndMessages(record);callback.dismiss(event);return true;}return false;
}private boolean isCurrentSnackbarLocked(Callback callback) {return mCurrentSnackbar != null && mCurrentSnackbar.isSnackbar(callback);
}private boolean isNextSnackbarLocked(Callback callback) {return mNextSnackbar != null && mNextSnackbar.isSnackbar(callback);
}// 更新超时提示
private void scheduleTimeoutLocked(SnackbarRecord r) {if (r.duration == Snackbar.LENGTH_INDEFINITE) {// If we're set to indefinite, we don't want to set a timeoutreturn;}int durationMs = LONG_DURATION_MS;if (r.duration > 0) {durationMs = r.duration;} else if (r.duration == Snackbar.LENGTH_SHORT) {durationMs = SHORT_DURATION_MS;}mHandler.removeCallbacksAndMessages(r);mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_TIMEOUT, r), durationMs);
}// 显示NextSnackbar,调用callback的show方法
private void showNextSnackbarLocked() {if (mNextSnackbar != null) {mCurrentSnackbar = mNextSnackbar;mNextSnackbar = null;final Callback callback = mCurrentSnackbar.callback.get();if (callback != null) {callback.show();} else {// The callback doesn't exist any more, clear out the SnackbarmCurrentSnackbar = null;}}
}

SnackbarshowView()会调用onViewShown()hideView(int)会调用onViewHidden(int)

final void showView() {... ...if (shouldAnimate()) {// If animations are enabled, animate it inanimateViewIn();} else {// Else if anims are disabled just call back nowonViewShown();}... ...
}final void hideView(@BaseCallback.DismissEvent final int event) {if (shouldAnimate() && mView.getVisibility() == View.VISIBLE) {animateViewOut(event);} else {// If anims are disabled or the view isn't visible, just call back nowonViewHidden(event);}
}void onViewShown() {SnackbarManager.getInstance().onShown(mManagerCallback);
}void onViewHidden(int event) {    SnackbarManager.getInstance().onDismissed(mManagerCallback);
}

SnackbarManageronShown(Callback)onDismissed(Callback)方法。

public void onShown(Callback callback) {synchronized (mLock) {if (isCurrentSnackbarLocked(callback)) {scheduleTimeoutLocked(mCurrentSnackbar);}}
}public void onDismissed(Callback callback) {synchronized (mLock) {if (isCurrentSnackbarLocked(callback)) {// If the callback is from a Snackbar currently show, remove it and show a new onemCurrentSnackbar = null;if (mNextSnackbar != null) {showNextSnackbarLocked();}}}
}

Android Snackbar控件相关推荐

  1. android toolbar控件,Android Toolbar控件

    1. Toolbar类 Toolbar是替代ActionBar的产物,低版本可以使用v7兼容包,使用Theme.AppCompat主题,并添加配置. false true 2. Toolbar配置 主 ...

  2. Android 开源控件与常用开发框架开发工具类

    Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...

  3. 轻松上手Snackbar控件

    一.前言 Snackbar 控件是 Material design 产物,它的作用是显示弹出消息,这个系统的 Toast 类似,但是它又有优于 Toast 的地方,它可以添加用户交互,如果需要,它可以 ...

  4. Android开源控件ViewPager Indicator的使用方法

     1月16日厦门 OSC 源创会火热报名中,奖品多多哦   摘要 Android开源控件ViewPager Indicator的使用介绍 ViewPagerIndicator 目录[-] 1. V ...

  5. 日历控件的android代码,Android日历控件PickTime代码实例

    Android日历控件PickTime代码实例 发布时间:2020-10-03 16:05:51 来源:脚本之家 阅读:86 作者:手撕高达的村长 最近做项目,需要设置用户的生日,所以做这样一个功能. ...

  6. android 获取控件高度_安卓开发入门教程UI控件_ImageView

    什么是ImageView ImageView是用于显示图片的UI控件. 基础样例 1.展示本地图片 效果图 代码 <ImageViewandroid:layout_width="wra ...

  7. xamarin.android 控件,Android 库控件 - Xamarin | Microsoft Docs

    Xamarin Android 库控件Xamarin.Android Gallery control 03/15/2018 本文内容 Gallery是一种布局小组件,用于显示水平滚动列表中的项,并将当 ...

  8. android 获取控件在屏幕中的坐标

    今天,简单讲讲android如何获取控件在屏幕中的坐标. 这个其实也很简单,但是昨天做一个功能时,需要功能控件的坐标做一些逻辑操作时,居然不知道怎么做.所以在网上查找了资料后,解决了这个问题.这里记录 ...

  9. Android图表控件MPAndroidChart——曲线图LineChart的使用(财富收益图)

    目录 前言 本文涉及文章 其他相关文章 1.数据准备 1.1 数据来源 2.曲线展示 2.1 MPAndroidChart获取 2.2 数据对象获取 2.3 数据展示 3.曲线完善 3.1 图表背景. ...

最新文章

  1. 判断一个序列是不是堆的方法
  2. 关于SQL 数据库表中的聚集索引和非聚集索引等
  3. Leetcode 90. 子集 II 解题思路及C++实现
  4. windows ternimal 使用
  5. tensorflow环境下的识别食物_在win10环境下进行tensorflow物体识别(ObjectDetection)训练...
  6. linux cd的帮助文件,linux查看命令帮助man命令详解在线手册
  7. Kubernetes 的自动伸缩你用对了吗?
  8. 设置linux环境变量
  9. mysql系列之4.mysql字符集
  10. 几岁孩子可以学python_编程python适合多大孩子学
  11. i5 7200u 计算机专业,i5 7200U理论性能对比_笔记本评测-中关村在线
  12. CIC滤波器原理及设计实现
  13. SQL Server 2000 打sp3补丁
  14. 第1章 初始JAVA
  15. 主题词是计算机自动提取,汉语关键词自动转换主题词方法的步骤
  16. 【MOS】RAC 环境中 gc block lost 和私网通信性能问题的诊断 (文档 ID 1674865.1)
  17. 反超苹果,微软重回全球市值第一!
  18. 程序化交易系统的搭建
  19. echarts网络拓扑图动态流程图
  20. 网购车平台易车与汽车之家

热门文章

  1. Angular入门学习笔记
  2. 树莓派 天猫精灵智能灯泡_智能灯泡即使在关闭时也会用完电吗?
  3. 重装系统时出现windows root\system32\ntoskrnl.exe 损坏或者丢失?解决方法。。。。。。
  4. Mysql中的三种循环
  5. shell脚本之遍历字符串数组
  6. RDP服务针对性攻击、钓鱼邮件攻击和勒索病毒家族Phobos研究
  7. Java 集合中汉字按自然顺序排序
  8. php 查看文件锁定状态_Photoshop脚本 查看当前图层的锁定状态
  9. 2020ICPR-化妆演示攻击
  10. Office与visio的快速下载与安装