安卓高级6 SnackBar
引言
文/李牧羊(简书作者)
原文链接:http://www.jianshu.com/p/2654e6bda3b1
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
在之前我有提到这一篇Android Design Support Library系列文章是关于SnackBar的,但是由于要用到CoordinatorLayout所以先翻译了一篇相关文章,如果还不了解的可以先看一下Android Design Support Library--使用CoordinatorLayout来处理滚动
,这一篇我们讲SnackBar,SnackBar其实就是Toast的升级版,他们之间最大的不同就是:SnackBar会对我们的操作提供一个轻量级的反馈,并且可以对点击事件做出响应,如果是在手机上使用一个SnackBar的话,我们会看到在屏幕底部出现一条简短的信息,如果是在更大的屏幕上这条信息应该会显示在左下角,并且当一个SnackBar显示的时候它是凌驾于当前所有屏幕元素之上的,我们在屏幕上一次只能显示一个SnackBar,如果这么讲不是很清楚的话,我们先来看一个小Demo,通过代码驱动理解是比较好的方式。
示例
根据SnackBar的特点,在屏幕上显示出不同的SnackBar,效果如下:
先看一下相关的API文档:
| 方法类型 | 方法 | 作用 |
|---|---|---|
| void | dismiss() | 使SnackBar消失 |
| int | getDuration() | 返回SnackBar的持续时间 |
| View | getView() | 返回当前SnackBar的View |
| boolean | isShown() | 判断该SnackBar是否正在显示 |
| boolean | isShownOrQueued() | 判断该SnackBar是否正在显示或者排队等待即将要显示 |
| static Snackbar | make(View view, int resId, int duration) | 新建一个用来显示信息的SnackBar |
| static Snackbar | make(View view, CharSequence text, int duration) | 同上 |
| Snackbar | setAction(int resId, View.OnClickListener listener) | 设置这个即将显示的SnackBar的动作 |
| Snackbar | setAction(CharSequence text, View.OnClickListener listener) | 同上 |
| Snackbar | setActionTextColor(ColorStateList colors) | 设置action的文字颜色(右边的) |
| Snackbar | setActionTextColor(int color) | 同上 |
| Snackbar | setCallback(Snackbar.Callback callback) | 设置一个回调,当SnackBar的可见性改变的时候调用 |
| Snackbar | setDuration(int duration) | 设置SnackBar信息的显示时间 |
| Snackbar | setText(int resId) | 更新SnackBar上显示的文字 |
| Snackbar | setText(CharSequence message) | 同上 |
| void | show() | 显示SnackBar,最后一定要调用这个方法,不然SnackBar不显示,联想Toast |
可以看到Demo上显示了三种不同的SnackBar,我们都知道SnackBar是Toast的升级版,但也说明了一个问题那就是SnackBar是用来显示消息的,同时根据你的需求不同可以对这些消息做出一定的响应动作,下面分析三种显示消息方式的不同: - 普通的SnackBar也许有的人并没有过多的需求,只是单纯地想把SnackBar当作一个显示消息的控件而已,那么可以很简单的在代码中这么使用:
Snackbar.make(mCoor, R.string.normal, Snackbar.LENGTH_SHORT).show();
对比一下我们的Toast方式:
Toast.makeText(MainActivity.this,R.string.normal,Toast.LENGTH_SHORT).show();
是不是很像,没错简单的使用的话SnackBar跟Toast并没有多大区别,但是动画效果上是有差异的,如果你注意到了这一点:
看,这个侧边滑动消失的效果只有当你使用CoordinatorLayout作为根布局才有,这就是为什么在写SnackBar之前我要先说明一下CoordinatorLayout的原因,如果你使用普通的LinearLayout或者RelativeLayout是不会有这种动画交互效果的,另外,注意SnackBar的make方法有两种重载方法,分别是:
make(View view, int resId, int duration)
和
make(View view, CharSequence text, int duration)
这里有三个参数,第一个参数View表示的意思是我们传入一个View,然后SnackBar会遍历整个View Tree来找到一个合适的View承载SnackBar的View,如果你想要实现上面的动画交互效果的话最好是传入CoordinatorLayout对象,第二个参数的话是两个重载方法不同的地方,有一种是我们熟知的:
Snackbar.make(mCoor, "普通的SnackBar", Snackbar.LENGTH_SHORT).show();
还有一种要求传入一个ID,注意这个ID并不是指其他的什么,就是你在string.xml文件中定义的字符串资源的ID,比如这样:
Snackbar.make(mCoor, R.string.normal, Snackbar.LENGTH_SHORT).show();
然后第三个参数是SnackBar的持续时间,只有三种:
1、Snackbar.LENGTH_INDEFINITE 一直显示直到另一个SnackBar出现或者主动调用了dismiss()方法
2、Snackbar.LENGTH_SHORT 显示较短的时间
3、Snackbar.LENGTH_LONG 显示较长的时间
但是官方文档是这么描述的:
either be one of the predefined lengths: LENGTH_SHORT, LENGTH_LONG, or a custom duration in milliseconds.
说是可以自定义显示时间,但是我自己试了确实不可以,应该是API文档的一个小bug,如果谁试成功了赶紧告诉我~~如果使用过Toast的话上面的应该很好理解,好了,如果你的业务中对SnackBar并没有更多的要求,那么最普通的SnackBar应该满足了,接下来看稍微高级一点的:
- 带回调的SnackBar:如果还不太清楚回调的话可以看看这个Android回调函数机制那点事 ,讲这个之前先提一点,如果我们想更加灵活的使用Snackbar的话最好是先持有它的引用,也就是:
private Snackbar mSnackBar原因很简单,你会发现上面提供的常用API中很多方法都是非静态方法并不是静态方法,你要调用的话只能通过SnackBar对象去调用。然后说SnackBar回调之前先说一下Action,SnackBar提供了一个setAction方法:
1、setAction(int resId, View.OnClickListener listener)
2、setAction(CharSequence text, View.OnClickListener listener)同样是两个重载方法,第一个参数跟前面解释的一样,第二个参数是我们熟知的对点击事件的监听,使用方法如下:
Snackbar.make(mCoor,R.string.callback,Snackbar.LENGTH_SHORT)
.setAction(R.string.UNDO, new View.OnClickListener() {
@Override public void onClick(View v) {
// do something }
}).show();看一下效果:
这里写图片描述当我们调用了setAction方法并且传入一个字符串之后,SnackBar的右下角就会呈现出我们传入的字符串,并且这个字符串是可点击的,我们可以在点击事件里面做出响应,比如说跳转Activity或者弹出一个Toast等等,这里默认你点击了这个Action这个SnackBar是会消失的。也就是无论你的duration参数设置的是一直显示还是显示多长时间都会消失。有些人可能对右下角这个文字的颜色不满足想要改变,没问题,你想到的Google都给你想好了,SnackBar专门提供了方法来更改Action的文字颜色:
1、setActionTextColor(ColorStateList colors)
2、setActionTextColor(int color)这里第一种方式不建议用,太复杂,你要想这么用也行:
Resources resource = (Resources) getBaseContext().getResources();
ColorStateList csl = (ColorStateList)
resource.getColorStateList(R.color.PeachPuff);
mSnackBar.setActionTextColor(csl);这是网上找到的一种方式,但是我还是推荐使用第二种方式来更改Action的文字颜色,可以看到是我们熟悉的传入一个int型的值,我提供如下几种方式更改:
1、mSnackBar.setActionTextColor(Color.rgb(232,44,123))
2、mSnackBar.setActionTextColor(Color.BLUE)
3、mSnackBar.setActionTextColor(Color.parseColor("#FFDAB9"));
对了,我还发现一种额外的方式,我们现在使用Android Studio创建新的Project时候系统都会默认在style.xml文件夹下面生成这个:
<style name="AppTheme" parent="The
e.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item> </style>
这里的<item name="colorAccent">@color/colorAccent</item>其实也可以更改Action文字颜色,而且默认的Action文字颜色就是这里设置的颜色,但是有一个缺点就是如果你改动了这里,那么很多Material Design控件的相关颜色都会改变,如果你看过我之前写的Android
Design Support Library--TextInputLayout的使用你会知道TextInputLayout下划线的颜色也是通过这个属性来更改的,所以为了稳定起见还是使用官方提供的方法去更改吧,我这纯属抖个机灵。
那么回到正题,讲讲SnackBar的回调,眼尖的朋友可能发现了,我的Demo里面带回调的SnackBar在弹出和消失的时候都会有Toast通知出现,其实就是使用了SnackBar自带的
setCallback(Snackbar.Callback callback)
方法,这里需要传入一个Snackbar.Callback callback 参数,其实这个,这个Callback 是SnackBar内部的一个抽象类,它内部有两个空实现的方法:
onDismissed(Snackbar snackbar, int event)
onShown(Snackbar snackbar)
顾名思义,我们可以可以分别在这两个方法中定义出当SnackBar消失和产生时我们需要做的事,这两个方法会在SnackBar消失和产生时被回调,打个比方:
mSnackBar.setCallback(new Snackbar.Callback() { @Override public
void onDismissed(Snackbar snackbar, int event) {
super.onDismissed(snackbar, event);
Toast.makeText(MainActivity.this,"SnackBar
Dismiss",Toast.LENGTH_SHORT).show(); } @Override public void
onShown(Snackbar snackbar) { super.onShown(snackbar);
Toast.makeText(MainActivity.this,"SnackBar
Show",Toast.LENGTH_SHORT).show(); } });
这样就实现了在SnackBar消失和产生时弹出Toast通知的动作,其他具体的逻辑可以自己去实现。
完全自定义你自己的SnackBar
如果你对上述使用还是不甚满意,那么接下来我教你怎么自定义你自己的SnackBar,说实话用到的场景并不多,但是学了就学个透彻,这一部分知识的灵感来自于没时间解释了,快使用Snackbar! ,SnackBar并没有提供更改背景或者其他样式的方法,但是我们可以通过查看源码来试试可不可以自定义自己样式,我们找到这么一段代码:
private Snackbar(ViewGroup parent) { mTargetParent = parent;
mContext = parent.getContext();
ThemeUtils.checkAppCompatTheme(mContext); LayoutInflater
inflater = LayoutInflater.from(mContext); mView = (SnackbarLayout)
inflater.inflate( R.layout.design_layout_snackbar, mTargetParent,
false);
}
最后一行的inflate是不是很熟悉,我们可不可以认为Snackbar的布局就是这么加载的,这个SnackBarLayout是在SnackBar内部定义的一个继承自LinearLayout的内部类:
public static class SnackbarLayout extends LinearLayout { private
TextView mMessageView; private Button mActionView; private int
mMaxWidth; private int mMaxInlineActionWidth;
看到这几个变量的定义,我已经确定了上面的想法,接下来我们找到上面代码加载的那段布局:
<merge
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="@+id/snackbar_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_weight="1"
android:paddingTop="14dp" android:paddingBottom="14dp"
android:paddingLeft="12dp" android:paddingRight="12dp"
android:textAppearance="@style/TextAppearance.Design.Snackbar.
Message" android:maxLines="2"
android:layout_gravity="center_vertical|left|start"
android:ellipsize="end" android:textAlignment="viewStart"/>
<Button android:id="@+id/snackbar_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp" android:layout_marginStart="0dp"
android:layout_gravity="center_vertical|right|end"
android:paddingTop="14dp" android:paddingBottom="14dp"
android:paddingLeft="12dp" android:paddingRight="12dp"
android:visibility="gone" android:textColor="?attr/colorAccent"
style="?attr/borderlessButtonStyle"/></merge>
看到这两个控件的ID了么
android:id="@+id/snackbar_text"
android:id="@+id/snackbar_action"
public View getView ()Returns the Snackbar's view.
这个方法可以返回我们SnackBar的View,那么这个View是什么,看源码:
那么第一个就是SnackBar左边显示的message,第二个就是我们设置了action时候显示的Button咯,这就简单了,如果你仔细看了上面提供的API文档你会发现有这么一个方法:
/** * Returns the {@link Snackbar}'s view. */
@NonNull public View getView() { return mView; }
找一下mView在哪里定义的:
private final SnackbarLayout mView;mView = (SnackbarLayout)
inflater.inflate( R.layout.design_layout_snackbar, mTargetParent,
false);
好了,这下一切都清楚了,接下里示范一下怎么自定义你自己的SnackBar:
private View view; ....省略中间代码 view =
mCustomSnackBar.getView();
if (view != null) {
view.setBackgroundColor(Color.parseColor("#7B68EE"));
//获取Snackbar的message控件,修改字体颜色
((TextView)view.findViewById(R.id.snackbar_text)).setTextColor(Color.parseColor("#FFDAB9"));
//添加图标
Snackbar.SnackbarLayout snackbarLayout = (Snackbar.SnackbarLayout) view;
//添加自定义布局,这里布局就包含了一个ImageView
//custom_layout是你自定义的布局
View add_view = LayoutInflater.from(view.getContext()).inflate(R.layout.custom_layout
, null);
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONT
ENT, LinearLayout.LayoutParams.WRAP_CONTENT);
p.gravity = Gravity.CENTER_VERTICAL; //数字表示新加的布局在SnackBar中的位
置,从0开始,取决于你SnackBar里面有多少个子View
snackbarLayout.addView(add_view, 0, p); }
最后一行,addView方法第二个参数表示新加的布局在SnackBar中的位置,注意不要超过总的View的个数不然会报错,message和Action text分别算一个View,其他的话注释已经写得很清楚就不一一解释了,这个代码呈现的效果如下:
项目源码
项目GitHub地址
另外,最近做了一个小Demo,主要是使用了ExplosionField 的View爆炸效果,效果图如下:
有兴趣的可以看看:GitHub地址
原文链接:http://www.jianshu.com/p/2654e6bda3b1
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
安卓高级6 SnackBar的更多相关文章
- 安卓高级 WebView的使用到 js交互
我们先来学习 怎么使用再到用js和安卓源生方法交互 WebView简单使用 此部分转载并做了补充 原博客 原因:比较简单不是很想在写,我只要写js交互部分 WebView可以使得网页轻松的内嵌到app ...
- 安卓高级3 Android应用Design Support Library完全使用实例
原作者:http://www.open-open.com/lib/view/open1433385856119.html 1 背景 上周一年一度的Google IO全球开发者大会刚刚结束,Google ...
- 安卓高级9 用原生intent分享
大家都用过安卓app时发现有个分享按钮如下: 所以今天特此分享用用原生完成: package qianfeng.com.simplesharedemo; import android.content. ...
- 安卓高级1 -----Xutil3 和Picasso使用
Xutils3 Xutils由于内部使用httpclient然而在安卓5.0谷歌发现httpclient出现不稳定的情况.于6.0完全弃用,所以作者升级到Xutils3替换原本网络模块 配置环境(St ...
- 【安卓高级】ViewPager视差动画效果
在安卓开发中,是否遇见过一些很酷的视差动画效果,当ViewPager滑动下一页的时候,页面内的各种元素也能跟随滑动做位移效果,整体看起来非常有活力. 关键的PageTransformer PageTr ...
- 安卓高级Fresco图片框架的时候
Fresco:2015FaceBook推出的 及其强大 支持webp图片格式 和渐进式图片加载 中文文档 使用方法 引入依赖 点击查看具体教程 基本使用步骤 在布局中使用其标签 <com.fac ...
- 安卓高级 Android图片缓存之初识Glide
前言: 前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架.技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实 ...
- 安卓高级EventBus使用详解
我本来想写但是在网上看了下感觉写得不如此作者写得好:http://www.jianshu.com/p/da9e193e8b03 前言:EventBus出来已经有一段时间了,github上面也有很多开源 ...
- 安卓高级 特效动画ExplosionField和 SmoothTransition
本教程所有图片为github上的所无法正常访问请科学上网 SmoothTransition 展示效果 github:源码地址 使用方法 你能通过一行代码使用上面所有的动画 @Override prot ...
随机推荐
- SQL语句 (一)
1 SQL语句分类: 数据查询语句(DQL): SELECT 数据操纵语言 (DML): INSERT.UPDATE.DELETE 数据定义语言 (DDL): 数据控制语言 (DCL): GRANT. ...
- 初学servlet之使用web.xml配置
先写两个servlet,之后展示web.xml配置 package app01c;import java.io.IOException;import java.io.PrintWriter;impor ...
- spring data jpa 组合条件查询封装
/** * 定义一个查询条件容器 * @author lee * * @param <T> */ public class Criteria<T> implements Spe ...
- windows版本的phantomjs-2.1.1-windows安装
windows版本的phantomjs-2.1.1-windows安装 1.下载 链接:http://pan.baidu.com/s/1dEUl6dN 密码:oij8 2.安装 下载好之后解压放到某个 ...
- JS 变量类型互相转换
转载自:http://zhaizhiyuan.blog.163.com/blog/static/1897672632009093147268/ Java中几种常用的数据类型之间转换方法: 1. sh ...
- hdu 4897 树链剖分(重轻链)
Little Devil I Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- Luogu1613 跑路
题目描述 小A的工作不仅繁琐,更有苛刻的规定,要求小A每天早上在6:00之前到达公司,否则这个月工资清零.可是小A偏偏又有赖床的坏毛病.于是为了保住自己的工资,小A买了一个十分牛B的空间跑路器,每秒钟 ...
- VK-Cup2017 Wild Card Round 2
来自FallDream的博客,未经允许,请勿转载,谢谢. Cf的Vkcup外卡赛2 上次round2和ditoly翻车了 所以只好来打打了 规则是给一道比较特殊的题目,你要找出较优的解 Unive ...
- OCP 认证考试报名费技巧题库051052053解析合格线
本人于2017年4月22日通过参加OCP考试,第一次参加,一天之内考了三门,三门一次性通过,052 - 95% ,053 - 86% ,051 - 100% 一.关于考试考试报名费: 052:158$ ...
- Python-闭包详解
在函数编程中经常用到闭包.闭包是什么,它是怎么产生的及用来解决什么问题呢.给出字面的定义先:闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)(想想Erlang的外层函数传入一个 ...