software-mansion/react-native-reanimated

Issue with scaling on Animated.ScrollView after scaling-based exit animation

Opened this issue · 0 comments

Description

When using a scale-based exit animations (such as ZoomOut or any other scale-based animations) on an Animated.ScrollView, there seems to be an issue where the scale value from the exit animation is cached (?), causing incorrect scaling behavior when the component is remounted. Specifically, after the ZoomOut animation has been executed, the subsequent ZoomIn animation does not scale the component up from the correct initial value when the visibility is toggled back on. Instead, it seems to start from the last scale value applied during the exit animation, resulting in the component not scaling properly.

This issue contrasts with other animated components, such as Animated.View, which correctly triggers both the ZoomIn and ZoomOut animations multiple times without retaining the incorrect scale value from the previous exit animation.

Expected Behavior

The ZoomIn animation should scale the component correctly from its initial state every time the Animated.ScrollView becomes visible, regardless of whether a ZoomOut, or any other scale-based exit animations such as custom exit animations, has been triggered previously.

Actual Behavior

The ZoomIn animation fails to scale the component up from the expected initial state if ZoomOut has been triggered before. Instead, it uses the last scale value set during the exit animation as the starting value, leading to a progressively smaller component on each toggle. For instance, if the component exits at a scale of 0.8, the next time it enters, it starts from 0.8, which makes the component appear smaller with each visibility toggle.

Code Example

export default function App() {
  const [visible, setVisible] = useState(false)
  return (
    <SafeAreaView style={styles.container}>
    {visible && (
      <>
    <Animated.ScrollView style={styles.content} entering={ZoomIn} exiting={ZoomOut}>
      <Text style={styles.paragraph}>
        Animated.ScrollView bug
      </Text>
    </Animated.ScrollView>
        <Animated.View style={styles.content} entering={ZoomIn} exiting={ZoomOut}>
      <Text style={styles.paragraph}>
        Animated.View is working
      </Text>
    </Animated.View>
    </>
    )}
    <Pressable onPress={() => setVisible(!visible)} style={styles.button}><Text style={styles.paragraph}>Toggle</Text></Pressable>
    </SafeAreaView>
  );
}

Working code example can be tested in iOS in this snack.

Screen Recording

Animated.View ✅

AnimatedView.mp4

Animated.ScrollView 🐞

AnimatedScrollView.mp4

Steps to reproduce

  1. Create an Animated.ScrollView with ZoomIn for entry and ZoomOut for exit animations.
  2. Toggle the visibility of the Animated.ScrollView using a button or another method (test this in an native environment, I have been testing in iOS)
  3. After the ZoomOut exit animation runs, toggle the visibility again.
  4. Observe that the ZoomIn animation does not scale the component correctly.

Snack or a link to a repository

https://snack.expo.dev/qrAntko0DsnZ0wppqbKKY

Reanimated version

3.6.1

React Native version

0.76.3

Platforms

iOS

JavaScript runtime

None

Workflow

Expo Go

Architecture

None

Build type

None

Device

iOS simulator

Device model

iPhone 15 Pro

Acknowledgements

Yes