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

BUG - Animated.FlatList / itemLayoutAnimation - ANDROID

Open JeanSilvany opened this issue 1 year ago • 5 comments

Description

Currently, there is a bug that occurs only on Android when using the itemLayoutAnimation in Animated.FlatList.

The animations work perfectly when an item enters, but when removing an item, there is always a UI bug where the last item becomes invisible during rendering. Sometimes, more than one item disappears as well.

Throughout various tests, I found that using the property contentContainerStyle={{ height: '100%' }} prevents the bug from occurring. I also noticed that sometimes the exit animation works perfectly if the item is being controlled by a useState / visible, but even then the last item remains invisible. But this is not the expected behavior for a list.

The current problem occurs only on Android, in both Debug and Release modes with a physical device.

The expectation is that the exit animations function perfectly in the List and that there are no invisible item bugs.

https://github.com/software-mansion/react-native-reanimated/assets/73763375/3595047f-1a54-49d8-8aaf-484e845d5243

Steps to reproduce

  • Add more than 2 items to the list
  • Remove any item that is not the last one.

Snack or a link to a repository

https://snack.expo.dev/@jeansilvany/reanimated-layout-issue

Reanimated version

3.7.1

React Native version

0.73.4

Platforms

Android

JavaScript runtime

None

Workflow

React Native

Architecture

Paper (Old Architecture)

Build type

Debug app & production bundle

Device

None

Device model

No response

Acknowledgements

Yes

JeanSilvany avatar Feb 26 '24 02:02 JeanSilvany

Same here!

BrunoADPaixao avatar Feb 26 '24 14:02 BrunoADPaixao

Same issue here!!

gabrielsoaresm94 avatar Feb 26 '24 14:02 gabrielsoaresm94

Same... spent days trying to find a workaround this, but failed

IbraDajani avatar Feb 26 '24 14:02 IbraDajani

The problem is fully reproducible, even in simulator

Updated reproduction for debugging

import React, { useState } from 'react';
import {
  Button,
  ColorValue,
  ListRenderItemInfo,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';

import Animated, {
  Layout,
  SlideInRight,
  SlideOutLeft,
} from 'react-native-reanimated';

export default function App() {
  const [data, setData] = useState<ColorValue[]>([]);

  const handleAddItem = (addItem: ColorValue) => {
    console.log('HERE', data);
    setData((oldState) => [...oldState, addItem]);
  };

  const handleRemoveItem = (removeItem: ColorValue) => {
    setData((oldState) => oldState.filter((item) => item !== removeItem));
  };

  const renderItem = ({ item }: ListRenderItemInfo<ColorValue>) => {
    return (
      <Animated.View entering={SlideInRight} exiting={SlideOutLeft}>
        <TouchableOpacity
          activeOpacity={0.8}
          style={[styles.item, { backgroundColor: item }]}
          onPress={() => handleRemoveItem(item)}>
          <Text>{item.toString()}</Text>
        </TouchableOpacity>
      </Animated.View>
    );
  };

  return (
    <View style={styles.container}>
      <Animated.FlatList
        itemLayoutAnimation={Layout}
        data={data}
        renderItem={renderItem}
        keyExtractor={(item) => item.toString()}
        ItemSeparatorComponent={() => <View style={styles.separator} />}
      />

      <Button
        title="Add Item"
        onPress={() =>
          handleAddItem(
            '#' +
              (0x1000000 + Math.random() * 0xffffff).toString(16).substr(1, 6)
          )
        }
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
  },
  item: {
    width: '100%',
    height: 80,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 15,
  },
  separator: {
    height: 10,
  },
});

Latropos avatar Feb 27 '24 12:02 Latropos

Any updates?

IgorDantasDev avatar Feb 27 '24 20:02 IgorDantasDev

Right now the best workaround is to hardcode height of your flatList. If for some reason you can't do it, you may consider sth like this: https://github.com/software-mansion/react-native-reanimated/pull/5758#pullrequestreview-1943414942

Latropos avatar Mar 18 '24 15:03 Latropos

Right now the best workaround is to hardcode height of your flatList. If for some reason you can't do it, you may consider sth like this: #5758 (review)

Hi @Latropos I checked you PR for the same... if you closely look at the video that you shared for the Test Plan... the item which is partially visible , and not fully visible doesn't animate correctly (you can look from 0:08 seconds of the video and closely observe the partially visible item above the yellow box ). I really appreciate your effort in putting out a solve for this issue, but any idea as why the above mentioned thing is occuring? and any potential fix for the same? Thanks

@chiratnachakraborty-betterhalf Unfortunately the problem seems to be located in native code, which means that providing the valid fix may be difficult and will take us a bit longer to deliver it.

but any idea as why the above mentioned thing is occurring?

Unfortunately we have plenty of ideas and have to check each one separately.

and any potential fix for the same?

You can replace flatList with ScrollView. It affects the performance though.

Latropos avatar Mar 22 '24 10:03 Latropos

@Latropos Thanks for replying... for now we have move forward with a different solution to handle this scenario. We have very large list so ScrollView is not an option for us unfortunately .

Thanks

Same problem. Any good news?

gakulakov avatar May 27 '24 12:05 gakulakov