安卓高级6 SnackBar
引言
文/李牧羊(简书作者)
原文链接:
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
在之前我有提到这一篇 系列文章是关于的,但是由于要用到所以先翻译了一篇相关文章,如果还不了解的可以先看一下 --使用来处理滚动 ,这一篇我们讲,其实就是Toast的升级版,他们之间最大的不同就是:会对我们的操作提供一个轻量级的反馈,并且可以对点击事件做出响应,如果是在手机上使用一个的话,我们会看到在屏幕底部出现一条简短的信息,如果是在更大的屏幕上这条信息应该会显示在左下角,并且当一个显示的时候它是凌驾于当前所有屏幕元素之上的,我们在屏幕上一次只能显示一个,如果这么讲不是很清楚的话,我们先来看一个小Demo,通过代码驱动理解是比较好的方式。
示例
根据的特点,在屏幕上显示出不同的,效果如下:
这里写图片描述
先看一下相关的API文档:
方法类型方法作用
void
()
使消失
int
()
返回的持续时间
View
()
返回当前的View
()
判断该是否正在显示
()
判断该是否正在显示或者排队等待即将要显示
make(View view, int resId, int )
新建一个用来显示信息的
make(View view, text, int )
同上
(int resId, View. )
设置这个即将显示的的动作
( text, View. )
同上
( )
设置的文字颜色(右边的)
(int color)
同上
(. )
设置一个回调,当的可见性改变的时候调用
(int )
设置信息的显示时间
(int resId)
更新上显示的文字
( )
同上
void
show()
显示,最后一定要调用这个方法,不然不显示,联想Toast
可以看到Demo上显示了三种不同的,我们都知道是Toast的升级版,但也说明了一个问题那就是是用来显示消息的,同时根据你的需求不同可以对这些消息做出一定的响应动作,下面分析三种显示消息方式的不同: - 普通的也许有的人并没有过多的需求,只是单纯地想把当作一个显示消息的控件而已,那么可以很简单的在代码中这么使用:
Snackbar.make(mCoor, R.string.normal, Snackbar.LENGTH_SHORT).show();
对比一下我们的Toast方式:
Toast.makeText(MainActivity.this,R.string.normal,Toast.LENGTH_SHORT).show();
是不是很像,没错简单的使用的话跟Toast并没有多大区别,但是动画效果上是有差异的,如果你注意到了这一点:
这里写图片描述
看,这个侧边滑动消失的效果只有当你使用作为根布局才有,这就是为什么在写之前我要先说明一下的原因,如果你使用普通的或者是不会有这种动画交互效果的,另外,注意的make方法有两种重载方法,分别是:
make(View view, int resId, int duration)
和
make(View view, CharSequence text, int duration)
这里有三个参数,第一个参数View表示的意思是我们传入一个View,然后会遍历整个View Tree来找到一个合适的View承载的View,如果你想要实现上面的动画交互效果的话最好是传入对象,第二个参数的话是两个重载方法不同的地方,有一种是我们熟知的:
Snackbar.make(mCoor, "普通的SnackBar", Snackbar.LENGTH_SHORT).show();
还有一种要求传入一个ID,注意这个ID并不是指其他的什么,就是你在.xml文件中定义的字符串资源的ID,比如这样:
Snackbar.make(mCoor, R.string.normal, Snackbar.LENGTH_SHORT).show();
然后第三个参数是的持续时间,只有三种:
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的话上面的应该很好理解,好了,如果你的业务中对并没有更多的要求,那么最普通的应该满足了,接下来看稍微高级一点的:
1、mSnackBar.setActionTextColor(Color.rgb(232,44,123))
2、mSnackBar.setActionTextColor(Color.BLUE)
3、mSnackBar.setActionTextColor(Color.parseColor("#FFDAB9"));
对了,我还发现一种额外的方式,我们现在使用 创建新的时候系统都会默认在style.xml文件夹下面生成这个:
<style name="AppTheme" parent="The
e.AppCompat.Light.DarkActionBar"> -- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary- "colorPrimaryDark"
>@color/colorPrimaryDark
- "colorAccent">@color/colorAccent
style>
这里的@color/其实也可以更改文字颜色,而且默认的文字颜色就是这里设置的颜色,但是有一个缺点就是如果你改动了这里,那么很多 控件的相关颜色都会改变,如果你看过我之前写的 --的使用你会知道下划线的颜色也是通过这个属性来更改的,所以为了稳定起见还是使用官方提供的方法去更改吧,我这纯属抖个机灵。
那么回到正题,讲讲的回调,眼尖的朋友可能发现了,我的Demo里面带回调的在弹出和消失的时候都会有Toast通知出现,其实就是使用了自带的
setCallback(Snackbar.Callback callback)
方法,这里需要传入一个. 参数,其实这个,这个 是内部的一个抽象类,它内部有两个空实现的方法:
onDismissed(Snackbar snackbar, int event)
onShown(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(); } });
这样就实现了在消失和产生时弹出Toast通知的动作,其他具体的逻辑可以自己去实现。
完全自定义你自己的
如果你对上述使用还是不甚满意,那么接下来我教你怎么自定义你自己的,说实话用到的场景并不多,但是学了就学个透彻,这一部分知识的灵感来自于没时间解释了,快使用! ,并没有提供更改背景或者其他样式的方法,但是我们可以通过查看源码来试试可不可以自定义自己样式,我们找到这么一段代码:
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);}
最后一行的是不是很熟悉,我们可不可以认为的布局就是这么加载的,这个是在内部定义的一个继承自的内部类:
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.
这个方法可以返回我们的View,那么这个View是什么,看源码:
那么第一个就是左边显示的,第二个就是我们设置了时候显示的咯,这就简单了,如果你仔细看了上面提供的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);
好了,这下一切都清楚了,接下里示范一下怎么自定义你自己的:
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); }
最后一行,方法第二个参数表示新加的布局在中的位置,注意不要超过总的View的个数不然会报错,和 text分别算一个View,其他的话注释已经写得很清楚就不一一解释了,这个代码呈现的效果如下:
这里写图片描述
项目源码
项目地址
另外,最近做了一个小Demo,主要是使用了 的View爆炸效果,效果图如下:
这里写图片描述
这里写图片描述
有兴趣的可以看看:地址
文/李牧羊(简书作者)
原文链接:
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。