react-native-reanimated icon indicating copy to clipboard operation
react-native-reanimated copied to clipboard

[Android] Layout animations enabled by default on android

Open maxencehenneron opened this issue 2 years ago • 10 comments

Description

Layout Animations are enabled by default on Android. The react-native doc says they are experimental on this platform:

https://reactnative.dev/docs/layoutanimation

I use layout animations on my app on iOS only and having them enabled on android breaks multiple parts of the app. Is it safe to just disable them again by calling the following code?

if (Platform.OS === 'android') {
  if (UIManager.setLayoutAnimationEnabledExperimental) {
    UIManager.setLayoutAnimationEnabledExperimental(false);
  }
}

Here's the line that enables them:

https://github.com/software-mansion/react-native-reanimated/blob/e52d733ab9f0fc33e52c54c8d7adbfe86a2608ac/android/src/main/java/com/swmansion/reanimated/layoutReanimation/ReanimatedNativeHierarchyManager.java#L259

Steps to reproduce

Just install react-native-reanimated, launch an app ( you can use the example ).

Snack or a link to a repository

https://github.com/software-mansion/react-native-reanimated/tree/main/Example

Reanimated version

2.9.0

React Native version

0.67.4

Platforms

Android

JavaScript runtime

Hermes

Workflow

No response

Architecture

No response

Build type

No response

Device

No response

Device model

No response

Acknowledgements

Yes

maxencehenneron avatar Oct 04 '22 22:10 maxencehenneron

Hey! 👋

The issue doesn't seem to contain a minimal reproduction.

Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?

github-actions[bot] avatar Oct 04 '22 22:10 github-actions[bot]

React Native Layout Animation are something completely different than LayoutAnimation by react-native-reanimated. And you should avoid using it at the current stage, until the rewrite is done, see https://github.com/software-mansion/react-native-reanimated/issues/3124

hirbod avatar Oct 06 '22 12:10 hirbod

Then why are React Native's layout animations enabled by default when you install this library?

https://github.com/software-mansion/react-native-reanimated/blob/e52d733ab9f0fc33e52c54c8d7adbfe86a2608ac/android/src/main/java/com/swmansion/reanimated/layoutReanimation/ReanimatedNativeHierarchyManager.java#L259

This line is called when initializing reanimated. If you look closely, ReanimatedNativeHierarchyManager inherits NativeViewHierarchyManager from React Native, so calling this enables React-Native's layout animations which are experimental on Android.

I am not using reanimated's LayoutAnimations but I have some libraries that use React Native's layout animations. Enabling react native's layout animations breaks those libraries so I have to re-disable it manually after reanimated initializes. My question is:

Is it safe to do? Why are react-native's layout animations enabled by default?

maxencehenneron avatar Oct 06 '22 15:10 maxencehenneron

You're referring to https://reactnative.dev/docs/layoutanimation, which has nothing to do with https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/layout_animations

hirbod avatar Oct 06 '22 16:10 hirbod

I know these are completely different. This is what I'm saying. react-native-reanimated is enabling react-native's layout animation which I believe should not happen, hence, I created this issue.

Screen Shot 2022-10-06 at 9 47 29 AM

If you put a breakpoint inside react-native's code to enable react-native's implementation of layout animations, you can clearly see that it is being enabled by react-native-reanimated. It should not.

maxencehenneron avatar Oct 06 '22 16:10 maxencehenneron

Kinda weird, but try this

import { enableLayoutAnimations } from 'react-native-reanimated';

enableLayoutAnimations(false);

hirbod avatar Oct 06 '22 16:10 hirbod

I experienced the same issue but with KeyboardAvoidingView on iOS 16.x, react-native 0.71.4 and reanimated 3.0.2

I had enableLayoutAnimations(true) and in every screen I had KeyboardAvoidingView I got this error when focusing and blur on a TextInput.

Warning: Overriding previous layout animation with new one before the first began: <RCTLayoutAnimationGroup: 0x6000037e8d50; creatingLayoutAnimation: (null); updatingLayoutAnimation: <RCTLayoutAnimation: 0x600002289280; duration: 0.250000; delay: 0.000000; property: (null); springDamping: 0.000000; initialVelocity: 0.000000; animationType: 5;>; deletingLayoutAnimation: (null)> -> (null).

after setting enableLayoutAnimations(false) the issue went away. I've lost 2 days trying to see what was going on.

edit: This was crashing/freezing iOS users, this is the native stacktrace:

Hardware Model:     iPhone12,1
Process:            app_name
Identifier:         app_name
Version:            2.0.8
Role:               Foreground
OS Version:         iOS 16.3.1


App Hang: The app was terminated while unresponsive

0  QuartzCore +0x12ba0        -[CALayer animationForKey:]
1  QuartzCore +0x12b90        -[CALayer animationForKey:]
2  UIKitCore +0xdb80          -[UIViewAnimationState _shouldAnimateAdditivelyForKey:onLayer:forView:]
3  UIKitCore +0xd3f0          -[UIViewAnimationState actionForLayer:forKey:forView:]
4  UIKitCore +0xd240          +[UIView(Animation) _defaultUIViewActionForLayer:forKey:]
5  UIKitCore +0xc900          -[UIView(UIKitManual) actionForLayer:forKey:]
6  QuartzCore +0xa054         -[CALayer actionForKey:]
7  QuartzCore +0x9ec8         CA::Layer::begin_change(CA::Transaction*, unsigned int, objc_object*, objc_object*&)
8  QuartzCore +0x2776c        CA::Layer::set_position(CA::Vec2<double> const&, bool)
9  QuartzCore +0xec34         -[CALayer setPosition:]
10 UIKitCore +0x264a4         -[UIView setCenter:]
11 app_name +0x40b328             -[UIView(React) reactSetFrame:] (UIView+React.m:204:8)
12 app_name +0x402558             -[RCTView reactSetFrame:] (RCTView.m:764:3)
13 UIKitCore +0xcfc58         +[UIView _setupAnimationWithDuration:delay:view:options:factory:animations:start:animationStateGenerator:completion:]
14 UIKitCore +0xa2ed4         +[UIView(UIViewAnimationWithBlocks) animateWithDuration:delay:options:animations:completion:]
15 app_name +0x3cc204             -[RCTLayoutAnimation performAnimations:withCompletionBlock:] (RCTLayoutAnimation.m:121:5)
16 app_name +0x35b758             __51-[REAUIManager uiBlockWithLayoutUpdateForRootView:]_block_invoke.46 (REAUIManager.mm:306:9)
17 app_name +0x3f9210             __44-[RCTUIManager flushUIBlocksWithCompletion:]_block_invoke (RCTUIManager.m:1199:9)
18 app_name +0x3f9300             __44-[RCTUIManager flushUIBlocksWithCompletion:]_block_invoke.146 (RCTUIManager.m:1219:5)
19 libdispatch.dylib +0x245c  __dispatch_call_block_and_release
20 libdispatch.dylib +0x3f84  __dispatch_client_callout
21 libdispatch.dylib +0x127f0 __dispatch_main_queue_drain
22 libdispatch.dylib +0x12440 __dispatch_main_queue_callback_4CF
23 CoreFoundation +0x9a6c4    ___CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
24 CoreFoundation +0x7c028    ___CFRunLoopRun
25 CoreFoundation +0x80eac    _CFRunLoopRunSpecific
26 GraphicsServices +0x1364   _GSEventRunModal
27 UIKitCore +0x3a1664        -[UIApplication _run]
28 UIKitCore +0x3a12c8        _UIApplicationMain
29 app_name +0x78a4               main (main.m:8:12)
30 dyld +0x1595c              start

edit 2: this is easily reproducible, just use a TextInput inside a KeyboardAvoidingView and enableLayoutAnimations(true). Just focus and blur on the TextInput

efstathiosntonas avatar Mar 22 '23 11:03 efstathiosntonas

Kinda weird, but try this

import { enableLayoutAnimations } from 'react-native-reanimated';

enableLayoutAnimations(false);

On my side I prefer to disable the react-native layout animation and the warning is gone too. Thanks for the hint 👍

import { UIManager } from 'react-native';

UIManager.setLayoutAnimationEnabledExperimental &&
  UIManager.setLayoutAnimationEnabledExperimental(false);

hatem-72 avatar Jun 01 '23 10:06 hatem-72

I also have this issue.

Using setLayoutAnimationEnabledExperimental does not seem to work for IOS so that still causes native react native layout animations and react-native-reanimated layout animations to stumble over each other when using KeyboardAvoidingView on that platform. Turning react-native-reanimated layout animations off gets rid of the issue but then obviously you miss the animations you want to keep.

@hatem-72 have you managed to get react-native-reanimated + KeyboardAvoidingView + IOS working?

tmitchel2 avatar Jun 12 '23 13:06 tmitchel2

I got this noisy warning from v3, it's show with IOS device

fukemy avatar Jun 15 '23 03:06 fukemy