diff --git a/apps/common-app/src/examples/LayoutAnimations/BottomTabs.tsx b/apps/common-app/src/examples/LayoutAnimations/BottomTabs.tsx
new file mode 100644
index 000000000000..60e8da8d6817
--- /dev/null
+++ b/apps/common-app/src/examples/LayoutAnimations/BottomTabs.tsx
@@ -0,0 +1,69 @@
+import React from 'react';
+
+import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
+import { View, StyleSheet, Button } from 'react-native';
+import Animated, {
+ BounceInDown,
+ FadeIn,
+ FadeOutDown,
+ LinearTransition,
+ RotateOutDownLeft,
+} from 'react-native-reanimated';
+
+const BottomBar = createBottomTabNavigator();
+
+const TabA = () => {
+ const [toggle, setToggle] = React.useState(false);
+
+ return (
+
+
+
+ );
+};
+
+const TabB = () => {
+ return (
+
+
+
+ );
+};
+
+const BottomTabsExample = () => {
+ return (
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ },
+ boxA: {
+ width: 100,
+ height: 100,
+ backgroundColor: 'blue',
+ },
+ boxB: {
+ width: 100,
+ height: 100,
+ backgroundColor: 'red',
+ },
+});
+
+export default BottomTabsExample;
diff --git a/apps/common-app/src/examples/index.ts b/apps/common-app/src/examples/index.ts
index 53d510fb606e..8cbdeeb5fe9b 100644
--- a/apps/common-app/src/examples/index.ts
+++ b/apps/common-app/src/examples/index.ts
@@ -131,6 +131,7 @@ import BorderRadiiExample from './SharedElementTransitions/BorderRadii';
import FreezingShareablesExample from './ShareableFreezingExample';
import TabNavigatorExample from './SharedElementTransitions/TabNavigatorExample';
import StrictDOMExample from './StrictDOMExample';
+import BottomTabsExample from './LayoutAnimations/BottomTabs';
import ListItemLayoutAnimation from './LayoutAnimations/ListItemLayoutAnimation';
interface Example {
@@ -706,6 +707,10 @@ export const EXAMPLES: Record = {
title: '[LA] Change theme',
screen: ChangeThemeExample,
},
+ BottomTabs: {
+ title: '[LA] Bottom Tabs',
+ screen: BottomTabsExample,
+ },
// Shared Element Transitions
diff --git a/packages/react-native-reanimated/Common/cpp/LayoutAnimations/LayoutAnimationsProxy.cpp b/packages/react-native-reanimated/Common/cpp/LayoutAnimations/LayoutAnimationsProxy.cpp
index f219e5d64617..b3a197d659e9 100644
--- a/packages/react-native-reanimated/Common/cpp/LayoutAnimations/LayoutAnimationsProxy.cpp
+++ b/packages/react-native-reanimated/Common/cpp/LayoutAnimations/LayoutAnimationsProxy.cpp
@@ -139,6 +139,8 @@ void LayoutAnimationsProxy::parseRemoveMutations(
std::unordered_map>>
childrenForTag, unflattenedChildrenForTag;
+ std::vector> mutationNodes;
+
// iterate from the end, so that parents appear before children
for (auto it = mutations.rbegin(); it != mutations.rend(); it++) {
auto &mutation = *it;
@@ -190,9 +192,7 @@ void LayoutAnimationsProxy::parseRemoveMutations(
}
}
- if (!unflattenedParent->parent) {
- roots.push_back(mutationNode);
- }
+ mutationNodes.push_back(mutationNode);
childrenForTag[parentTag].push_back(mutationNode);
unflattenedChildrenForTag[unflattenedParentTag].push_back(mutationNode);
@@ -209,10 +209,24 @@ void LayoutAnimationsProxy::parseRemoveMutations(
}
for (auto &[parentTag, children] : childrenForTag) {
- nodeForTag_[parentTag]->insertChildren(children);
+ auto &parent = nodeForTag_[parentTag];
+ parent->insertChildren(children);
+ for (auto &child : children) {
+ child->parent = parent;
+ }
}
for (auto &[unflattenedParentTag, children] : unflattenedChildrenForTag) {
- nodeForTag_[unflattenedParentTag]->insertUnflattenedChildren(children);
+ auto &unflattenedParent = nodeForTag_[unflattenedParentTag];
+ unflattenedParent->insertUnflattenedChildren(children);
+ for (auto &child : children) {
+ child->unflattenedParent = unflattenedParent;
+ }
+ }
+
+ for (auto &mutationNode : mutationNodes) {
+ if (!mutationNode->unflattenedParent->isMutationMode()) {
+ roots.push_back(mutationNode);
+ }
}
}
@@ -697,6 +711,7 @@ void LayoutAnimationsProxy::transferConfigFromNativeID(
auto nativeId = stoi(nativeIdString);
layoutAnimationsManager_->transferConfigFromNativeID(nativeId, tag);
} catch (std::invalid_argument) {
+ } catch (std::out_of_range) {
}
}