question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Android] "Remove animations" setting isn't reflected when using `AccessibilityInfo`

See original GitHub issue

Description

  • When removing animations through “Android settings” -> “Accessibility” -> “Remove animations”, it doesn’t seem to result in AccessibilityInfo.isReduceMotionEnabled() returning true or the change event to fire.
  • When going through “Android settings” -> “Developer settings” -> “Animator duration scale” -> “Off”, it works as expected.

Note that setting “Remove animations” will also set “Animator duration scale” to “Off”, but only manually setting it to “Off” again will result in AccessibilityInfo.isReduceMotionEnabled() to return true

Thus, both settings seem to be in sync somehow, but the setting in Accessibility (available to all users, not just developers) didn’t seem to have the desired effect in my tests.

I tested on Android 10 and 11.

React Native version:

0.63.2 (expo SDK 39)

Steps To Reproduce

see description

Expected Results

When setting “Remove animations” in Android’s accessibility settings AccessibilityInfo.isReduceMotionEnabled() returns true

Snack, code example, screenshot, or link to a repository:

My best guess is that Settings.Global.TRANSITION_ANIMATION_SCALE is somehow not set to the expected value when using the “Remove animations” switch instead of the related developer setting. See https://github.com/facebook/react-native/blob/0.63-stable/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.java#L100

This is the hook I’m using

import { useEffect, useState } from 'react';
import {
  AccessibilityChangeEventHandler,
  AccessibilityInfo,
} from 'react-native';

export function useReduceMotionEnabled(): [boolean] {
  const [reduceMotionEnabled, setReduceMotionEnabled] = useState(false);

  useEffect(() => {
    AccessibilityInfo.addEventListener(
      'reduceMotionChanged',
      handleReduceMotionToggled,
    );
    AccessibilityInfo.isReduceMotionEnabled().then((reduceMotionEnabled) => {
      setReduceMotionEnabled(reduceMotionEnabled);
    });

    return () => {
      AccessibilityInfo.removeEventListener(
        'reduceMotionChanged',
        handleReduceMotionToggled,
      );
    };
  }, []);

  const handleReduceMotionToggled: AccessibilityChangeEventHandler = (
    state,
  ) => {
    setReduceMotionEnabled(state);
  };

  return [reduceMotionEnabled];
}

This issue might be related: https://github.com/facebook/react-native/issues/30871

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:1
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
horsemankukkacommented, May 1, 2022

My best guess is that Settings.Global.TRANSITION_ANIMATION_SCALE is somehow not set to the expected value when using the “Remove animations” switch instead of the related developer setting.

This is exactly what is happening here.

The “correct” but strictly undocumented check for the accessibility preference seems to be value.equals("0"), as that’s what Android sets the value to when the accessibility preference is set. Flutter does the equivalent check this way.

The other, probably more preferable option is to use getFloat instead and check that value == 0.0f, like Chromium does. This way both using Developer settings and Accessibility settings triggers the feature.

(In contrast, the Android API docs specify that the value is a float and that setting the value to 0.0f should always disable animations, but this weird “type overloading” carrying a single bit of information about who set the preference makes the situation very confusing, so in practice the result is different in every app.)

Disclaimer: I am not an Android coder, I discovered this weirdness today. Found this issue by chance, so decided to share my findings here in case it helps fixing this problem. I don’t consider myself experienced enough with this project altogether to make a PR.

0reactions
joshbucheacommented, Mar 10, 2022

We would love to be able to respect our user’s preference to reduce motion on Android. Is there anything we can do to help move this along?

I’m not familiar enough with Java to create a PR, but am happy to help otherwise. What’s the process for triaging an issue?

Appreciate any help or guidance anyone is able to offer, thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to check status of Remove Animations accessibility ...
I'm trying to check for the status of Remove animations accessibility setting in order to enable/disable ...
Read more >
How to disable interface animations in Android 13
Open the Accessibility settings. 1. Open the Settings app. Scroll down and select Accessibility.
Read more >
AccessibilityNodeInfo - Android Developers
Class with information of a view useful to evaluate accessibility needs. ... Accessibility services should not care about these bounds.
Read more >
Diff - 8e3feb15c5aec2c72b0ef120a1da325e1e8f0dda^! - platform ...
LongArray was not removing elements properly. 4. ... service has + * to declare the capability to retrieve window content by setting the...
Read more >
Animated - React Native
Value , hook it up to one or more style attributes of an animated component, and then drive updates via animations using Animated.timing()...
Read more >

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found