software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
8.78k stars 1.28k forks source link

[Android] Layout animations enabled by default on android #3643

Open maxencehenneron opened 1 year ago

maxencehenneron commented 1 year ago

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

github-actions[bot] commented 1 year ago

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?

hirbod commented 1 year ago

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

maxencehenneron commented 1 year ago

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?

hirbod commented 1 year ago

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

maxencehenneron commented 1 year ago

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.

hirbod commented 1 year ago

Kinda weird, but try this

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

enableLayoutAnimations(false);
efstathiosntonas commented 1 year ago

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

hatem-72 commented 1 year ago

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);
tmitchel2 commented 1 year ago

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?

fukemy commented 1 year ago

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