software-mansion / react-native-reanimated

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

Entering layout animation jump on initial render #5952

Open matinzd opened 2 months ago

matinzd commented 2 months ago

Description

There is an initial jump when calculating the boundaries of the view when using layout animations on initial render. It is more obvious on iOS but it also happens a bit on Android.

https://github.com/software-mansion/react-native-reanimated/assets/24797481/26f2baf6-da82-448b-816e-07ca7fc9095c

Steps to reproduce

  1. Add some views with space between them
  2. Add some views after other views and apply entering animation
  3. Add some delay to it to see the jump and increase the duration

Snack or a link to a repository

https://snack.expo.dev/@matinzd/reanimated-layout-animation-bug

Reanimated version

3.9.0

React Native version

0.74.0

Platforms

Android, iOS

JavaScript runtime

Hermes

Workflow

React Native

Architecture

Paper (Old Architecture)

Build type

Debug app & production bundle

Device

Real device

Device model

iPhone 12 Pro

Acknowledgements

Yes

matinzd commented 2 months ago

Update:

I realized that even without adding space or margin between items, the bug is still present. I have updated the reproducible example.

Wrapping it in another view will fix the issue on iOS but it is still broken on Android.

exploIF commented 1 month ago

Hi @matinzd, regarding Android issue I cannot reproduce it with your example.

Regarding iOS issue I've take a look on your repro and I've managed to fix it by providing additional container for all your components rendered directly inside SafeAreaView (not only for the Animated.View itself). It is because SafeAreaView is adding padding which is somehow making animated component to jump afer animation is completed. We will take a look on this behavior closer.

Please check my code

import { Text, SafeAreaView, StyleSheet, View } from 'react-native';
import Animated, { FadeIn } from 'react-native-reanimated';
import { Card } from 'react-native-paper';
import AssetExample from './components/AssetExample';

const animation = FadeIn.delay(1000).duration(2000);

export default function App() {
  return (
    <SafeAreaView style={{flex: 1}}>
      <View style={styles.container}>
        <Text style={styles.paragraph}>
            Test text to expand the size between
          </Text>
          <Text style={styles.paragraph}>
            Test text to expand the size between
          </Text>
          <Animated.View entering={animation}>
            <Card>
              <AssetExample />
            </Card>
          </Animated.View>
      </View>
    </SafeAreaView>
  );
}
const styles = StyleSheet.create({
  container: {
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
  },
  paragraph: {
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
  },
});
exploIF commented 1 month ago

We've decided to add a warning message when animated component is rendered directly inside SafeAreaView. Also, this will be added to Troubleshooting section in our docs too.