解决SnackBar无动画现象
编辑更新(2018年10月22日)
在新的 material-components-android
库中(版本号: 1.0.0-alpha3
),已经修复了这个bug,support库中的Snackbar依旧存在这个问题,此篇文章仅供参考使用。感谢 Trumeet
的提醒。
以下为原文:
发现问题
突然间不知道从什么时候开始,手机上的app只要是调用了SnackBar的地方,SnackBar显示都没有效果,这两天突然开始察觉到这个问题了,开始各种google,但是都没有找到直接让SnackBar没有动画的结果(中文),甚至我还以为是SnackBar的源码改了。 但是又觉得不对,google的这个SnackBar新控件非常不错,不应该把动画去掉啊。 为此,我特意将design包的版本回退到22.2.0版本,依旧是没有动画。 这里开始我就觉得不对了,google不可能去掉并且旧版本依旧没有动画,那么应该是我的配置上的问题。 想到这里,我开始去查看CoordinatorLayout的用法,但是依旧没有任何卵用。
解决问题
突然间我想到了一个问题,会不会是国内还没有察觉到这个问题,但是国外有了呢,我是不相信全世界就我一个人有这个问题的。 抱着试一试的态度,我开始google snackbar no animation,果不其然,找到了许多和我相同的问题。
简单的查看了一下,有的人说是开发者选项中的动画缩放(?)的问题,但是我试了依旧错误,继续看才看到一个回答是辅助功能导致的。
查看我手机上的辅助功能选项,发现打开了一个服务——冰箱的后台服务。
将这个服务关闭之后,再次打开应用,SnackBar的动画显示出来了。
说在后面
继续查看了这个问题,但是没有看出什么来,只是提供了一个方法,使用AccessibilityManager.isEnabled()来判断辅助功能是否开启,但是我在代码中添加提示错误,AccessibilityManager是一个final类,这个类中使用了单例模式,一个static方法返回实例,但是我在调用这个静态方法的时候报错,提示找不到这个方法,查看源码AccessibilityManager类是公有的,静态方法也是公有的,但是报错,不知道为什么,如果有人知道为什么的请告诉我。
2017年8月3日更新:
时间过去了五个月,今天我总算是找到了解决方法。
前面我们已经说了SnackBar没有动画是因为开启了无障碍服务,在 SnackBar
的父类 BaseTransientBottomBar
中会检测无障碍服务的开启状况,偏偏 SnackBar
是 final
类,看起来似乎有点无解,继承 SnackBar
重写是肯定不行的。
幸运的是,我在StackOverFlow上找到一个解决方法,参考链接。
这个方法是利用反射将 AccessibilityManager
类在app中调用的对象的 mIsEnabled
属性值改为 false
,这样就能通过 BaseTransientBottomBar
的检测,同时系统的无障碍服务并没有关闭,也不影响使用。
为了方便使用,我将这一段代码添加到了我自己的库中,这样我只需要直接在 Application
中初始化这样一句话就能够实现无视无障碍服务开启状况显示 SnackBar
的动画。以下是我的代码:
object ASnackBar
{
private val TAG = "ASnackBar"
@JvmStatic fun disableAccessibility(context: Context)
{
val contextThemeWrapper = ContextThemeWrapper(context, R.style.Theme_AppCompat)
val view = LayoutInflater.from(contextThemeWrapper).inflate(R.layout.mystery0_snack_bar_coordinator_layout, null)
Snackbar.make(view, "SnackBar", Snackbar.LENGTH_SHORT)
.apply {
try
{
val mAccessibilityManagerField = BaseTransientBottomBar::class.java.getDeclaredField("mAccessibilityManager")
mAccessibilityManagerField.isAccessible = true
val accessibilityManager = mAccessibilityManagerField.get(this)
val mIsEnabledField = AccessibilityManager::class.java.getDeclaredField("mIsEnabled")
mIsEnabledField.isAccessible = true
mIsEnabledField.setBoolean(accessibilityManager, false)
mAccessibilityManagerField.set(this, accessibilityManager)
}
catch (e: Exception)
{
Logs.e(TAG, "disableAccessibility: $e")
}
}
}
}
2018年10月22日更新:
由于上面的代码在部分定制系统会出问题,并且已经不再更新ToolsDemo库了,所以删掉以下内容,上述代码仅供参考,直接用也行(如果不怕booooooooooooom的话~)
使用时只需要这样的一行代码即可搞定,当然,前提你需要使用我的这个ToolsDemo
库。
ASnackBar.disableAccessibility(this);
参考列表
java - SnackBar appear animation - Stack Overflow
Issue 206416: Snackbar no longer slides onto screen
Snackbar and other animations stopped working on some Android devices
- 0
- 0
-
分享