Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layout Animations for the New Architecture #6055

Merged
merged 85 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
6ae1904
first attempt
bartlomiejbloniarz Feb 14, 2024
96157bb
semi-working approach (issue with flickering)
bartlomiejbloniarz Feb 20, 2024
e0c0fcb
new approach (no flickering, but only ios works)
bartlomiejbloniarz Feb 26, 2024
1b5ba60
No flicker (android is broken when nesting because of the threading m…
bartlomiejbloniarz Mar 12, 2024
46bd2ab
Rewrite
bartlomiejbloniarz Mar 22, 2024
3ace8a9
Add abstraction for exiting animations
bartlomiejbloniarz Mar 22, 2024
649f7bf
Minor exiting fixes
bartlomiejbloniarz Mar 26, 2024
a0aee0a
Add logic for removal
bartlomiejbloniarz Mar 27, 2024
9b5ac82
Fix indices
bartlomiejbloniarz Mar 27, 2024
9e50bb1
Add window dimensions and better RNSStack handling
bartlomiejbloniarz Mar 28, 2024
583ae94
Cleanup
bartlomiejbloniarz Mar 28, 2024
43131f8
Cleanup 2
bartlomiejbloniarz Mar 28, 2024
a303ce0
Cleanup 3
bartlomiejbloniarz Mar 28, 2024
97503e0
Cleanup 4
bartlomiejbloniarz Apr 3, 2024
3ed1dd2
Stable iOS
bartlomiejbloniarz Apr 3, 2024
c2dd306
Fix flickering on android
bartlomiejbloniarz Apr 4, 2024
95b954e
Stable android (but flickers came back :(()
bartlomiejbloniarz Apr 4, 2024
f1d734c
(hope)fully stable android with no flickers
bartlomiejbloniarz Apr 4, 2024
210d8ac
Minor fixes + skip exiting
bartlomiejbloniarz Apr 19, 2024
38432f6
Cleanup
bartlomiejbloniarz Apr 19, 2024
824f1ec
Restore DefaultAnimations.tsx
bartlomiejbloniarz Apr 19, 2024
dbbf721
merg main
bartlomiejbloniarz Apr 19, 2024
23c31e3
Fixes after merge
bartlomiejbloniarz Apr 22, 2024
e53959a
Change nativeId
bartlomiejbloniarz Apr 23, 2024
a9b22c9
Fix window dimensions for multiple surfaces
bartlomiejbloniarz Apr 23, 2024
1e27e46
Mock global origin
bartlomiejbloniarz Apr 23, 2024
508e344
Undo unnecessary changes
bartlomiejbloniarz Apr 23, 2024
530116a
Rename + import sort function from RN
bartlomiejbloniarz Apr 23, 2024
b4c2f2a
Simplify layout metrics
bartlomiejbloniarz Apr 23, 2024
917c2b5
Reorder + rename + simplify
bartlomiejbloniarz Apr 23, 2024
8c89659
Restore original opacity in entering
bartlomiejbloniarz Apr 23, 2024
4802fa7
Move layout animation objects initialization to helper functions
bartlomiejbloniarz Apr 23, 2024
8584976
Trigger mount for the updated surface only
bartlomiejbloniarz Apr 24, 2024
23e1e02
Handle cleanup mutations separately for surfaces
bartlomiejbloniarz Apr 24, 2024
1871c77
Move to utils
bartlomiejbloniarz Apr 26, 2024
8ec6add
Refactor MutationNode
bartlomiejbloniarz Apr 26, 2024
6afb037
Cleanup
bartlomiejbloniarz Apr 26, 2024
a53a72a
Restore progressTransitionManager
bartlomiejbloniarz Apr 26, 2024
1dfc738
Hide logging behind ifdef
bartlomiejbloniarz Apr 26, 2024
40286c1
Handle stoi exception
bartlomiejbloniarz Apr 29, 2024
4e7483e
Format
bartlomiejbloniarz Apr 29, 2024
914e208
Cleanup logs
bartlomiejbloniarz Apr 29, 2024
90b2a25
Simplify indices
bartlomiejbloniarz May 13, 2024
e9af8b1
Fix cleanup conflicting with exiting on indices
bartlomiejbloniarz May 13, 2024
6462106
Change a bunch of booleans to a single state variable
bartlomiejbloniarz May 14, 2024
9a290b1
merg
bartlomiejbloniarz May 14, 2024
f9b9600
Add workaround for nativeID to DefaultAnimationsExample
bartlomiejbloniarz May 14, 2024
4434d4b
Fix timing issues with animation override
bartlomiejbloniarz May 16, 2024
270001b
Cleanup
bartlomiejbloniarz May 16, 2024
3cb83a7
Add clear config call
bartlomiejbloniarz May 20, 2024
7af17fb
Fix android props update and reorders
bartlomiejbloniarz May 27, 2024
f9575a6
Cleanup
bartlomiejbloniarz May 27, 2024
b6b1ca9
Update Podfile.lock
bartlomiejbloniarz May 27, 2024
6ef2d0f
Make LayoutAnimationsProxy a friend of NativeReanimatedModule
bartlomiejbloniarz May 27, 2024
c56d753
Remove fake friends :((
bartlomiejbloniarz May 27, 2024
83b769e
Fix build issues
bartlomiejbloniarz May 28, 2024
a0ca2b2
Run formatting
bartlomiejbloniarz May 28, 2024
2e46168
Fix linter issues
bartlomiejbloniarz May 28, 2024
988bbef
Add a workaround for screen header
bartlomiejbloniarz May 28, 2024
23c829c
forgor
bartlomiejbloniarz May 28, 2024
914fa0d
merg
bartlomiejbloniarz May 28, 2024
ae11faf
refactor
bartlomiejbloniarz May 29, 2024
9f66f96
Fix skipEntering
bartlomiejbloniarz Jun 3, 2024
49a8462
Add comments
bartlomiejbloniarz Jun 3, 2024
67e3824
Add view flattening handling
bartlomiejbloniarz Jun 10, 2024
2d22cb4
merg monorepo
bartlomiejbloniarz Jun 10, 2024
490ce6b
Avoid starting animations for non-layout updates
bartlomiejbloniarz Jun 11, 2024
9e8e437
Remove IS_FABRIC const
bartlomiejbloniarz Jun 14, 2024
b60a5cd
Remove unnecessary SET init
bartlomiejbloniarz Jun 14, 2024
97ba232
Move BBexample
bartlomiejbloniarz Jun 14, 2024
00d4f99
Rename nativeID
bartlomiejbloniarz Jun 14, 2024
c958290
Separate LA init logic and entering configs
bartlomiejbloniarz Jun 14, 2024
1ff01f9
Refactor utils
bartlomiejbloniarz Jun 14, 2024
2030b22
Extract opacity fix
bartlomiejbloniarz Jun 14, 2024
becab04
Extract LayoutAnimation creation
bartlomiejbloniarz Jun 14, 2024
2527050
Add threading comment
bartlomiejbloniarz Jun 14, 2024
acdffdc
Fix formatting
bartlomiejbloniarz Jun 14, 2024
292e9e5
Add isMutationNode virtual function
bartlomiejbloniarz Jun 14, 2024
a0a1a04
Fix Gemfile.lock
bartlomiejbloniarz Jun 17, 2024
0b5fd8a
Fix android
bartlomiejbloniarz Jun 17, 2024
953c2d7
Change default animations example
bartlomiejbloniarz Jun 17, 2024
5d3d03c
Add info to docs
bartlomiejbloniarz Jun 17, 2024
9ff3572
Separate exiting config
bartlomiejbloniarz Jun 17, 2024
64ffcf4
Add comment
bartlomiejbloniarz Jun 17, 2024
6478644
Merge branch 'main' into @bartlomiejbloniarz/fabric-layout-animations
bartlomiejbloniarz Jun 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions apps/common-app/src/examples/LayoutAnimations/BBExample.tsx
bartlomiejbloniarz marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Button, StyleSheet, View } from 'react-native';
import Animated, {
BounceIn,
FadeInRight,
FadeInUp,
FadeOutLeft,
LinearTransition,
RotateOutDownLeft,
} from 'react-native-reanimated';
import React, { useState } from 'react';

export default function BBExample() {
const [show, setShow] = useState(true);
const [show2, setShow2] = useState(false);

return (
<View style={styles.container}>
<Button title="toggle" onPress={() => setShow(!show)} />
<Button title="toggle" onPress={() => setShow2(!show2)} />
{show && (
<Animated.View
onTouchStart={() => setShow(!show)}
entering={BounceIn}
layout={LinearTransition}
style={styles.box}
exiting={FadeOutLeft.duration(1000)}>
<Animated.View
style={styles.innerBox}
exiting={RotateOutDownLeft.duration(2000)}
entering={FadeInRight.delay(500)}
/>
</Animated.View>
)}
{show2 && (
<Animated.View
entering={FadeInUp}
layout={LinearTransition.duration(2000)}
exiting={RotateOutDownLeft}
style={[styles.refresher, { width: show ? 200 : 100 }]}
/>
)}
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
marginTop: 200,
backgroundColor: 'pink',
},
box: {
marginTop: 10,
width: 200,
height: 100,
backgroundColor: 'tomato',
},
innerBox: {
marginTop: 10,
width: 100,
height: 50,
backgroundColor: 'green',
},
refresher: {
marginTop: 10,
width: 100,
height: 100,
backgroundColor: 'blue',
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,12 @@ const AnimatedBlock = ({
<View style={styles.animatedBox}>
{show ? (
<TouchableWithoutFeedback onPress={() => setShow(!show)}>
<Animated.View style={styles.animatedBlock} {...animatedStyle}>
<Text style={styles.animatedText}>{name}</Text>
</Animated.View>
{/* Workaround for TouchableWithoutFeedback overwriting the nativeID */}
bartlomiejbloniarz marked this conversation as resolved.
Show resolved Hide resolved
<View>
<Animated.View style={styles.animatedBlock} {...animatedStyle}>
<Text style={styles.animatedText}>{name}</Text>
</Animated.View>
</View>
</TouchableWithoutFeedback>
) : null}
{!show ? (
Expand Down
32 changes: 6 additions & 26 deletions apps/common-app/src/examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ import WithClampExample from './WithClampExample';
import WorkletFactoryCrash from './WorkletFactoryCrashExample';
import RuntimeTestsExample from './RuntimeTests/RuntimeTestsExample';
import HabitsExample from './LayoutAnimations/HabitsExample';
import BBExample from './LayoutAnimations/BBExample';
import MemoExample from './MemoExample';
import PerformanceMonitorExample from './PerfomanceMonitorExample';
import ScreenTransitionExample from './ScreenTransitionExample';
Expand Down Expand Up @@ -502,7 +503,6 @@ export const EXAMPLES: Record<string, Example> = {
icon: '🧑‍💻',
title: 'Habits',
screen: HabitsExample,
missingOnFabric: true,
},
PerformanceMonitorExample: {
icon: '⏱️',
Expand All @@ -524,6 +524,11 @@ export const EXAMPLES: Record<string, Example> = {
title: 'Composed handler internal merging',
screen: ComposedHandlerInternalMergingExample,
},
BBExample: {
icon: '💀',
title: 'BB',
screen: BBExample,
},

// Old examples

Expand Down Expand Up @@ -598,127 +603,102 @@ export const EXAMPLES: Record<string, Example> = {
DeleteAncestorOfExiting: {
title: '[LA] Deleting view with an exiting animation',
screen: DeleteAncestorOfExiting,
missingOnFabric: true,
},
NestedNativeStacksWithLayout: {
title: '[LA] Nested NativeStacks with layout',
screen: NestedNativeStacksWithLayout,
missingOnFabric: true,
},
BasicLayoutAnimation: {
title: '[LA] Basic layout animation',
screen: BasicLayoutAnimation,
missingOnFabric: true,
},
BasicNestedAnimation: {
title: '[LA] Basic nested animation',
screen: BasicNestedAnimation,
missingOnFabric: true,
},
BasicNestedLayoutAnimation: {
title: '[LA] Basic nested layout animation',
screen: BasicNestedLayoutAnimation,
missingOnFabric: true,
},
NestedLayoutAnimations: {
title: '[LA] Nested layout animations',
screen: NestedTest,
missingOnFabric: true,
},
CombinedLayoutAnimations: {
title: '[LA] Entering and Exiting with Layout',
screen: CombinedTest,
missingOnFabric: true,
},
DefaultAnimations: {
title: '[LA] Default layout animations',
screen: DefaultAnimations,
missingOnFabric: true,
},
DefaultTransitions: {
title: '[LA] Default layout transitions',
screen: WaterfallGridExample,
missingOnFabric: true,
},
KeyframeAnimation: {
title: '[LA] Keyframe animation',
screen: KeyframeAnimation,
missingOnFabric: true,
},
ParticipantList: {
title: '[LA] Participant List',
screen: AnimatedListExample,
missingOnFabric: true,
},
OlympicAnimation: {
title: '[LA] Olympic animation',
screen: OlympicAnimation,
missingOnFabric: true,
},
CustomLayoutAnimation: {
title: '[LA] Custom layout animation',
screen: CustomLayoutAnimationScreen,
missingOnFabric: true,
},
ModalNewAPI: {
title: '[LA] ModalNewAPI',
screen: ModalNewAPI,
missingOnFabric: true,
},
SpringLayoutAnimation: {
title: '[LA] Spring Layout Animation',
screen: SpringLayoutAnimation,
missingOnFabric: true,
},
MountingUnmounting: {
title: '[LA] Mounting Unmounting',
screen: MountingUnmounting,
missingOnFabric: true,
},
ReactionsCounterExample: {
title: '[LA] Reactions counter',
screen: ReactionsCounterExample,
missingOnFabric: true,
},
SwipeableList: {
title: '[LA] Swipeable list',
screen: SwipeableList,
missingOnFabric: true,
},
Modal: {
title: '[LA] Modal',
screen: Modal,
missingOnFabric: true,
},
NativeModals: {
title: '[LA] Native modals (RN and Screens)',
screen: NativeModals,
missingOnFabric: true,
},
Carousel: {
title: '[LA] Carousel',
screen: Carousel,
missingOnFabric: true,
},
ReducedMotionLayoutExample: {
title: '[LA] Reduced Motion',
screen: ReducedMotionLayoutExample,
missingOnFabric: true,
},
NestedLayoutAnimationConfig: {
title: '[LA] Nested LayoutAnimationConfig',
screen: NestedLayoutAnimationConfig,
missingOnFabric: true,
},
FlatListSkipEnteringExiting: {
title: '[LA] FlatList skip entering & exiting',
screen: FlatListSkipEnteringExiting,
missingOnFabric: true,
},
ChangeTheme: {
title: '[LA] Change theme',
screen: ChangeThemeExample,
missingOnFabric: true,
},

// Shared Element Transitions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ Reanimated comes with a bunch of predefined animations you can customize. For mo
## Remarks

- We recommend using layout animation builders outside of components or with `useMemo` to ensure the best performance.
- On the New Architecture:
- `nativeID` is used internally to configure entering animations, so overwriting it will result in entering animations not running. Some components (e.g. TouchableWithoutFeedback) overwrite `nativeID` of its children. To work around this issue wrap your animated children with a `View`.
- removing a non-animated view will trigger exiting animations in its children, but the non-animated view will not wait for the children's animations to finish. This is due to view flattening and can be mitigated by using `collapsable={false}`.

## Fade

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ void LayoutAnimationsManager::configureAnimationBatch(
clearSharedTransitionConfig(tag);
sharedTransitionConfigs.push_back(std::move(layoutAnimationConfig));
} else {
#ifdef RCT_NEW_ARCH_ENABLED
if (type == ENTERING){
enteringAnimationsForNativeID_[tag] = config;
continue;
}
#endif
if (config == nullptr) {
getConfigsForType(type).erase(tag);
} else {
Expand Down Expand Up @@ -159,6 +165,19 @@ int LayoutAnimationsManager::findPrecedingViewTagForTransition(const int tag) {
return -1;
}

#ifdef RCT_NEW_ARCH_ENABLED
void LayoutAnimationsManager::transferConfigFromNativeID(
const int nativeId,
const int tag) {
auto lock = std::unique_lock<std::recursive_mutex>(animationsMutex_);
auto config = enteringAnimationsForNativeID_[nativeId];
if (config) {
enteringAnimations_.insert_or_assign(tag, config);
}
enteringAnimationsForNativeID_.erase(nativeId);
}
#endif

#ifndef NDEBUG
std::string LayoutAnimationsManager::getScreenSharedTagPairString(
const int screenTag,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class LayoutAnimationsManager {
void clearLayoutAnimationConfig(const int tag);
void clearSharedTransitionConfig(const int tag);
void cancelLayoutAnimation(jsi::Runtime &rt, const int tag) const;
#ifdef RCT_NEW_ARCH_ENABLED
void transferConfigFromNativeID(const int nativeId, const int tag);
#endif
int findPrecedingViewTagForTransition(const int tag);
#ifndef NDEBUG
std::string getScreenSharedTagPairString(
Expand All @@ -63,6 +66,9 @@ class LayoutAnimationsManager {
std::unordered_map<int, std::string> viewsScreenSharedTagMap_;
#endif

#ifdef RCT_NEW_ARCH_ENABLED
std::unordered_map<int, std::shared_ptr<Shareable>> enteringAnimationsForNativeID_;
#endif
std::unordered_map<int, std::shared_ptr<Shareable>> enteringAnimations_;
std::unordered_map<int, std::shared_ptr<Shareable>> exitingAnimations_;
std::unordered_map<int, std::shared_ptr<Shareable>> layoutAnimations_;
Expand Down
Loading
Loading