Snackbar and other animations stopped working on some Android devices

前端 未结 3 532
情书的邮戳
情书的邮戳 2021-01-31 18:12

I have a very odd issue that I cannot figure out. I was not an issue until recently but I can\'t seem to revert back to prevent it. Also the other odd thing is it works on some

相关标签:
3条回答
  • 2021-01-31 19:01

    As Bignadad mentioned, the problem is that any accessibility feature, including things like password managers, disables the snackbar animations. Google, as of this edit, has fixed this for AndroidX but not the Design support library

    Because Snackbar's base class, BaseTransientBottomBar, handles the animation, with package private, final methods, you have two choices if you want to fix it: roll your own snackbar from scratch, or use a more hacky solution with reflection:

    Kotlin example:

    // Only force when necessary, and don't animate when TalkBack or similar services are enabled
    val shouldForceAnimate = !accessibilityManager.isEnabled && accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty()
    
    Snackbar.make(coordinatorLayout, text, duration).apply {
        if (shouldForceAnimate) {
            try {
                val accManagerField = BaseTransientBottomBar::class.java.getDeclaredField("mAccessibilityManager")
                accManagerField.isAccessible = true
                val accManager = accManagerField.get(this)
                AccessibilityManager::class.java.getDeclaredField("mIsEnabled").apply {
                    isAccessible = true
                    setBoolean(accManager, false)
                }
                accManagerField.set(this, accManager)
            } catch (e: Exception) {
                Log.d("Snackbar", "Reflection error: $e")
            }
        }
    }.show()
    

    Java example:

    // Only force when necessary, and don't animate when TalkBack or similar services are enabled
    boolean shouldForceAnimate = !accessibilityManager.isEnabled() && accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN).size == 0;
    
    Snackbar snackbar = Snackbar.make(coordinatorLayout, text, duration);
    if(shouldForceAnimate){
        try {
            Field accManagerField = BaseTransientBottomBar.class.getDeclaredField("mAccessibilityManager");
            accManagerField.setAccessible(true);
            AccessibilityManager accManager = (AccessibilityManager) accManagerField.get(snackbar);
            Field isEnabledField = AccessibilityManager.class.getDeclaredField("mIsEnabled");
            isEnabledField.setAccessible(true);
            isEnabledField.setBoolean(accManager, false);
            accManagerField.set(snackbar, accManager);
        } catch (Exception e) {
            Log.d("Snackbar", "Reflection error: " + e.toString());
        }
    }
    snackbar.show();
    

    I'd love a third option here, but I'm not aware of one, at least until AndroidX gets out of beta with the proper fix.

    0 讨论(0)
  • 2021-01-31 19:06

    This has been fixed since Material Components for Android 1.0.0-alpha3 with this commit.

    Use it instead of the Design Library (which is the way to go if you're using AndroidX):

    implementation "com.google.android.material:material:$material_components_version"
    
    0 讨论(0)
  • I found the reason why this is happening, but not how to fix yet.

    /**
     * Returns true if we should animate the Snackbar view in/out.
     */
    private boolean shouldAnimate() {
        return !mAccessibilityManager.isEnabled();
    }
    

    That is called by Snackbar class and is false on working devices, and true on devices not working. Does anyone know about this?

    So after i disabled lastpass in my system settings, accessibility the snackbar now animates as it should. That is crazy how that works. Nova launcher has the same affect. I guess any service in accessibility that is enabled will cause the snackbar animation to not work.

    0 讨论(0)
提交回复
热议问题