Snackbar和Toast的花式使用,系统Toast的存在的问题
系统toast存在的问题:
https://mp.weixin.qq.com/s/HQoAa5h-u8q32iWhs7dz_w
Foreword
这一篇是建立在我赌5毛你没见过这样的SpannableString基础上的,所以不会使用SpanUtils
的小伙伴快去看看吧。
这一篇我会写得详尽一些,毕竟是为了一劳永逸,让大家也尽可能了解我是怎么做到的,这里,我会用图文结合的方式来为大家开车,好了,开车,嘟嘟嘟嘟~。
Introduce
Snackbar
首先,我介绍下Snackbar,它是support.design
包下的一个widget
,和Toast
用途一样,可用来提示用户操作后的结果,但显示一般是在屏幕底部,较大的设备会在左下角显示,而且同一时间只能显示一条,它可以自动消失,也可以用户手动取消,但和Toast
不同的是它会伴随Activity
的结束而消失,其在绝对布局中还支持侧滑消失,其用法也和Toast
很像,具体基本使用可以自行上网了解,我这里主要讲解其高端使用。
下面我简单介绍一下SnackbarUtils
的API,后面演示我会一一细说。
Snackbar相关→SnackbarUtils.java→Demo
-
with : 设置snackbar依赖view
-
setMessage : 设置消息
-
setMessageColor: 设置消息颜色
-
setBgColor : 设置背景色
-
setBgResource : 设置背景资源
-
setDuration : 设置显示时长
-
setAction : 设置行为
-
show : 显示snackbar
-
showSuccess : 显示预设成功的snackbar
-
showWarning : 显示预设警告的snackbar
-
showError : 显示预设错误的snackbar
-
dismiss : 消失snackbar
-
getView : 获取snackbar视图
-
addView : 添加snackbar视图
下面我来为其演示,说了那么多,总算要上图了。
short_snackbar
有些朋友可能会惊讶,卧槽,怎么和我平时看到的Snackbar
不太一样,顶部是两圆角,前面还有图标,下面请听老司机分析,先上个代码压压惊。
-
SnackbarUtils.with(snackBarRootView)
-
.setMessage(getMsg(R.string.snackbar_short))
-
.setMessageColor(Color.WHITE)
-
.setBgResource(R.drawable.shape_top_round_rect)
-
.show();
实现如上效果,只需要以上代码即可,首先我们需要为Snackbar
传递其parent
视图,我用的是with()
操作,用过Glide
的小伙伴们肯定都知道with()
,我觉得这词很好,所以也就拿来用了,后面setMessage()
就是设置展示的消息了,其中参数为getMsg(xxx)
,这是现实图标的关键,下面放上源码。
-
private SpannableStringBuilder getMsg(@StringRes int resId) {
-
return new SpanUtils()
-
.appendLine(getString(resId))
-
.setFontSize(24, true)
-
.setIconMargin(R.mipmap.ic_launcher, 32, SpanUtils.ALIGN_CENTER)
-
.append(" ").setFontSize(0)
-
.create();
-
}
看到了吧,这里我使用的是SpannableString
,因为展示的消息的容器是TextView
,所以可以用各种SpannableString
,搭配上我上一篇文章我赌5毛你没见过这样的SpannableString,用起来不要太爽,这里我用的是它的setIconMargin()
来设置图标,因为这是属于段落型的SpannableString
,所以我要把appendLine()
产生的新行,用字体大小为0append(" ").setFontSize(0)
代替,从而看起来只有一行存在。为了方便起见,我把设置消息字体颜色setMessageColor()
和设置背景色setBgColor()
及设置背景资源setBgResource()
抽离了出来,所以顶部的两个圆角实现也是一语道破了,其用的是setBgResource()
。
图中显示的第二个Snackbar
右侧还有可点击按钮,源码如下所示。
-
SnackbarUtils.with(snackBarRootView)
-
.setMessage(getMsg(R.string.snackbar_short))
-
.setMessageColor(Color.WHITE)
-
.setBgResource(R.drawable.shape_top_round_rect)
-
.setAction(getString(R.string.snackbar_click), Color.YELLOW, new View.OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
ToastUtils.showShort(getString(R.string.snackbar_click));
-
}
-
})
-
.show();
这里只比之前多了个setAction()
,就是设置点击相关的文字,字体颜色及点击事件。
默认如果不写setDuration()
,那么Snackbar
的显示时长为短时,Snackbar
显示时长共包括三种,可以在setDuration()
中传入SnackbarUtils.LENGTH_SHORT
、SnackbarUtils.LENGTH_LONG
、SnackbarUtils.LENGTH_INDEFINITE
分别表示短时、长时、永久,这里我就不重复演示了。
如果SpanUtils
都满足不了各位大佬们的需求,别急,这里柯基实现了其他的接口来帮助你们,这里提醒一下,Snackbar
追求的是简洁明了,不要太过花里胡哨哈。
下面展示一下自定义的Snackbar
,如下图所示。
custom_snackbar
结合以下源码。
-
SnackbarUtils.with(snackBarRootView)
-
.setBgColor(Color.TRANSPARENT)
-
.setDuration(SnackbarUtils.LENGTH_INDEFINITE)
-
.show();
-
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
-
SnackbarUtils.addView(R.layout.snackbar_custom, params);
这里可以看到我们把Snackbar
的背景设为了透明setBgColor(Color.TRANSPARENT)
,然后先调用了show()
,因为只有先show()
出来之后,我们才能获取到Snackbar
的视图,然后对其加入我们自定义视图addView()
即可。
但显示的第二个Snackbar
还拥有点击消失的功能,这又是怎么实现的呢,其实答案已经呼之欲出了,我们只需要得到该视图即可,也就是API中的getView()
,然后就是你们随心所欲的操作了,源码如下所示。
-
View snackbarView = SnackbarUtils.getView();
-
if (snackbarView != null) {
-
TextView tvSnackbarCustom = (TextView) snackbarView.findViewById(R.id.tv_snackbar_custom);
-
tvSnackbarCustom.setText("点我可消失");
-
snackbarView.setOnClickListener(new View.OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
SnackbarUtils.dismiss();
-
}
-
});
-
}
在此,Snackbar
的高端玩法已经基本介绍完毕,除此之外,柯基还为大佬们封装了常用的几种,showSuccess
、showWarning
、showError
,其效果如下图所示。
others_snackbar
方便快捷调用代码如下所示。
-
case R.id.btn_show_success:
-
SnackbarUtils.with(snackBarRootView)
-
.setMessage(getMsg(R.string.snackbar_success))
-
.showSuccess();
-
break;
-
case R.id.btn_show_warning:
-
SnackbarUtils.with(snackBarRootView)
-
.setMessage(getMsg(R.string.snackbar_warning))
-
.showWarning();
-
break;
-
case R.id.btn_show_error:
-
SnackbarUtils.with(snackBarRootView)
-
.setMessage(getMsg(R.string.snackbar_error))
-
.showError();
-
break;
好了,第一部分Snackbar
的花式使用已介绍完毕,下面来说说大同小异的Toast
。
Toast
Toast
这玩意家喻户晓,其基本使用我就不介绍了,需要注意的就是在show()
之前要把之前的Toast
取消掉,否则的话Toast
会在队列中排队等待,造成不能及时得到当前需要的;还有一点就是异步show()
的话也会报错,这些最基本的在ToastUtils
都有解决。我们来看下其API介绍。
吐司相关→ToastUtils.java→Demo
-
setGravity : 设置吐司位置
-
setView : 设置吐司view
-
getView : 获取吐司view
-
setBackgroundColor : 设置背景颜色
-
setBackgroundResource: 设置背景资源
-
setMessageColor : 设置消息颜色
-
showShortSafe : 安全地显示短时吐司
-
showLongSafe : 安全地显示长时吐司
-
showShort : 显示短时吐司
-
showLong : 显示长时吐司
-
cancel : 取消吐司显示
可以看到其包括setView()
及getView()
,没错,有了它们,就可以设置自定义视图了。下面我从最基本用法开始介绍吧,先上图。
normal_toast
可以看到包括短时和长时的Toast
两类,我只介绍其一,另一种同理,显示短时Toast
的源码如下所示。
-
case R.id.btn_show_short_toast_safe:
-
new Thread(new Runnable() {
-
@Override
-
public void run() {
-
ToastUtils.showShortSafe(R.string.toast_short_safe);
-
}
-
}).start();
-
break;
-
case R.id.btn_show_short_toast:
-
ToastUtils.showShort(R.string.toast_short);
-
break;
可以看到我在异步的时候调用的是showShortSafe()
,这样就可以安全地使用了,是不是很简洁,只需要传入你要显示的内容即可,而且连续show()
也没什么问题。
作为常用操作,还支持设置文字颜色、背景颜色及背景资源,我们看下演示。
font_bg_toast
源码很简单,我就不做过多解释了,如下所示。
-
case R.id.btn_show_green_font:
-
ToastUtils.setMessageColor(Color.GREEN);
-
ToastUtils.showLong(R.string.toast_green_font);
-
break;
-
case R.id.btn_show_custom_bg:
-
ToastUtils.setBgResource(R.drawable.shape_round_rect);
-
ToastUtils.showLong(R.string.toast_custom_bg);
-
break;
花式使用?没错,又到了我们的SpanUtils
上场了,所以,没了解的小伙伴们还不赶快去看看我赌5毛你没见过这样的SpannableString来提升逼格,再来秀一波。
span_toast
源码如下,和之前介绍Snackbar
大相径庭,这里就不细说了。
-
case R.id.btn_show_span:
-
ToastUtils.showLong(new SpanUtils()
-
.appendLine(getString(R.string.toast_span))
-
.setFontSize(24, true)
-
.setIconMargin(R.mipmap.ic_launcher, 32, SpanUtils.ALIGN_CENTER)
-
.append(" ").setFontSize(0)
-
.create());
-
break;
同理,如果SpanUtils
满足不了你的需求,那我们就自定义吧,不过Toast
真的要这么花哨么,这是在搞事情,上图了。
custom_toast
源码如下,用得真是太简单了,为你们解放双手。
-
case R.id.btn_show_custom_view:
-
ToastUtils.setView(R.layout.toast_custom);
-
ToastUtils.showLong("");
-
break;
last but not least,Toast
还支持位置的变动,我就演示一下居中显示,如下所示。
middle_toast
源码如下,通俗易懂。
-
case R.id.btn_show_middle:
-
ToastUtils.setGravity(Gravity.CENTER, 0, 0);
-
ToastUtils.showLong(R.string.toast_middle);
-
break;
好了,Toast
相关已介绍完毕。
Conclusion
大佬们不用担心使用SnackbarUtils
和ToastUtils
会出现内存泄漏的问题,我一开始设计的时候就使用了弱引用来规避这个问题,所以还不放心大胆来使用他们吧,再配合上SpanUtils
,你们也可以玩出花来了,独乐乐不如众乐乐。