Android进阶之路view三千码友在身旁

使用Snackbar替换Toast

2019-11-26  本文已影响0人  pphdsny

背景

Toast是Android平台较常用的基础提示控件,使用简单易用;但是,Toast是系统层面提供的,不依赖于前台页面,存在滥用的风险。为了规避这些风险,Google在Android系统版本的迭代过程中,不断进行了优化和限制。这些限制不可避免的影响到了正常的业务逻辑,在迭代过程中,我们遇到过以下几个问题:

  1. 设置中关闭某个App的【显示通知】开关,Toast不再弹出,极大的影响了用户体验。
  2. Toast在Android 7.1.2(API25)以下会发生BadTokenException异常,导致App崩溃。
  3. 自定义TYPE_TOAST类型的Window,在Android 7.1.1、7.1.2发生token null is not valid异常,导致App崩溃。

当然了,上面这些问题,多少有一些替代方案,比如以下这些方式:

image

经过对比和参考美团实践方案,最终采用Snackbar对Toast进行替换。

使用Snackbar存在的一些问题

  1. Snackbar弹出的时候,被Dialog,PopupWindow等控件遮住。
  2. Snackbar无法进行跨页面展示,这是Snackbar实现原理决定的。
  3. Snackbar无法自定义布局、动画等

解决方案

问题一:

针对Snackbar弹出的时候,被Dialog,PopupWindow等控件遮住的问题,原因在于Snackbar依赖于View,当把Activity布局的View传给Snackbar做为Snackbar展示依赖的父View时,后面再弹Dialog,PopupWindow等控件,Snackbar就会被控件遮挡。正确的做法是直接把PopupWindow和Dialog所依赖的View传给Snackbar。那么我们定制化的Snackbar不仅支持传递这个View,也支持直接传递PopupWindow和Dialog的实例

问题二:

跨页面存在两种情况:

  1. Snackbar#show → startActivity
  2. Snackbar#show → finish

这两种情况都是在弹出Snackbar之后所依赖的Activity不可见或者关闭导致无法正常显示。所以将消息缓存起来,后置到下一个可见Activity进行处理,通过 application.registerActivityLifecycleCallbacks 进行页面onStart监听实现

问题三:

系统的Snackbar不支持自定义扩展,所以参考Snackbar的源码,进行了按需定制。

如何使用

#正常单页面使用
SnackbarUtils#showToast

#针对自定义View容器(会相对于View容器大小居中对齐,最好使用FrameLayout)
SnackbarUtils#showToastForView

#针对跨页使用
SnackbarUtils#showToastForJump

#针对Dialog使用
SnackbarUtils#showToastForDialog

简而言之:请在合适的时候、合适的场景、使用合适的API

当前版本兼容

注意:如继续使用ToastUtils中相关API,还是会老的Toast进行展示

不支持的情况(请使用Toast)

上一篇下一篇

猜你喜欢

热点阅读