Skip to content

Commit c245a1a

Browse files
MatiPl01tomekzaw
andauthored
(cherry pick) Fix sticky header (#7708)
Cherry-pick of the #7668 --------- Co-authored-by: Tomasz Zawadzki <[email protected]>
1 parent 66fff90 commit c245a1a

File tree

4 files changed

+66
-3
lines changed

4 files changed

+66
-3
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react';
2+
import { StyleSheet, Text } from 'react-native';
3+
import Animated, {
4+
useAnimatedScrollHandler,
5+
useAnimatedStyle,
6+
useSharedValue,
7+
} from 'react-native-reanimated';
8+
9+
const styles = StyleSheet.create({
10+
stickyHeader: {
11+
height: 80,
12+
backgroundColor: 'navy',
13+
},
14+
listItem: {
15+
padding: 16,
16+
},
17+
});
18+
19+
export default function StickyHeaderExample() {
20+
const offset = useSharedValue(0);
21+
22+
const scrollHandler = useAnimatedScrollHandler((event) => {
23+
offset.value = event.contentOffset.y;
24+
});
25+
26+
const animatedStyle = useAnimatedStyle(() => {
27+
return { transform: [{ translateY: offset.value }] };
28+
});
29+
30+
return (
31+
<Animated.ScrollView onScroll={scrollHandler}>
32+
<Animated.View style={[styles.stickyHeader, animatedStyle]} />
33+
{Array.from({ length: 100 }).map((_, i) => (
34+
<Text key={i} style={styles.listItem}>
35+
Item {i + 1}
36+
</Text>
37+
))}
38+
</Animated.ScrollView>
39+
);
40+
}

apps/common-app/src/examples/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ import RestoreStateExample from './SharedElementTransitions/RestoreState';
124124
import TabNavigatorExample from './SharedElementTransitions/TabNavigatorExample';
125125
import TransitionRestartExample from './SharedElementTransitions/TransitionRestart';
126126
import SharedStyleExample from './SharedStyleExample';
127+
import StickyHeaderExample from './StickyHeaderExample';
127128
import StrictDOMExample from './StrictDOMExample';
128129
import SvgExample from './SvgExample';
129130
import SwipeableListExample from './SwipeableListExample';
@@ -380,6 +381,11 @@ export const EXAMPLES: Record<string, Example> = {
380381
title: 'useScrollViewOffset',
381382
screen: ScrollViewOffsetExample,
382383
},
384+
StickyHeaderExample: {
385+
icon: '🔝',
386+
title: 'Sticky header',
387+
screen: StickyHeaderExample,
388+
},
383389
DispatchCommandExample: {
384390
icon: '🫡',
385391
title: 'Dispatch command',

packages/react-native-reanimated/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@ void ReanimatedCommitHook::maybeInitializeLayoutAnimations(
5252
RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
5353
ShadowTree const &,
5454
RootShadowNode::Shared const &,
55-
RootShadowNode::Unshared const &newRootShadowNode) noexcept {
55+
RootShadowNode::Unshared const &newRootShadowNode
56+
#if REACT_NATIVE_MINOR_VERSION >= 80
57+
,
58+
const ShadowTreeCommitOptions &commitOptions
59+
#endif
60+
) noexcept {
5661
maybeInitializeLayoutAnimations(newRootShadowNode->getSurfaceId());
5762

5863
auto reaShadowNode =
@@ -89,8 +94,15 @@ RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
8994
// PropsRegistry.
9095
// This is very important, since if we didn't pause Reanimated commits,
9196
// it could lead to RN commits being delayed until the animation is finished
92-
// (very bad).
97+
// (very bad). We don't pause Reanimated commits for state updates coming
98+
// from React Native as this would break sticky header animations.
99+
#if REACT_NATIVE_MINOR_VERSION >= 80
100+
if (commitOptions.source == ShadowTreeCommitSource::React) {
101+
propsRegistry_->pauseReanimatedCommits();
102+
}
103+
#else
93104
propsRegistry_->pauseReanimatedCommits();
105+
#endif
94106
}
95107

96108
return rootNode;

packages/react-native-reanimated/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ class ReanimatedCommitHook
3232
RootShadowNode::Unshared shadowTreeWillCommit(
3333
ShadowTree const &shadowTree,
3434
RootShadowNode::Shared const &oldRootShadowNode,
35-
RootShadowNode::Unshared const &newRootShadowNode) noexcept override;
35+
RootShadowNode::Unshared const &newRootShadowNode
36+
#if REACT_NATIVE_MINOR_VERSION >= 80
37+
,
38+
const ShadowTreeCommitOptions &commitOptions
39+
#endif
40+
) noexcept override;
3641

3742
private:
3843
std::shared_ptr<PropsRegistry> propsRegistry_;

0 commit comments

Comments
 (0)