Skip to main content
Version: 0.4.0

Collapsible Headers

Reanimated Tab View supports collapsible headers that smoothly collapse as the user scrolls content within any tab. This is a common pattern seen in apps like Instagram profiles.

Basic setup

To add a collapsible header, use the renderHeader prop along with RTVScrollView or RTVFlatList inside your scenes:

import { TabView, RTVScrollView } from 'reanimated-tab-view';

function MyTabView() {
const renderHeader = ({ collapsedPercentage, collapsedHeaderHeight }) => (
<View style={{ height: 200 }}>
<Text>Profile Header</Text>
</View>
);

const renderScene = ({ route }) => {
switch (route.key) {
case 'posts':
return (
<RTVScrollView>
{/* Your scrollable content */}
</RTVScrollView>
);
default:
return null;
}
};

return (
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
renderHeader={renderHeader}
onIndexChange={setIndex}
initialLayout={{
tabView: { width: layout.width },
tabViewHeader: { height: 200 },
}}
/>
);
}

Header renderer props

The renderHeader callback receives HeaderRendererProps:

PropTypeDescription
collapsedPercentageSharedValue<number>Animated value from 0 (expanded) to 100 (fully collapsed)
collapsedHeaderHeightSharedValue<number>Animated value representing the current collapsed height

You can use these shared values to create animated header effects:

import Animated, { useAnimatedStyle, interpolate } from 'react-native-reanimated';

const renderHeader = ({ collapsedPercentage }) => {
const animatedStyle = useAnimatedStyle(() => ({
opacity: interpolate(collapsedPercentage.value, [0, 100], [1, 0]),
}));

return (
<Animated.View style={[{ height: 200 }, animatedStyle]}>
<Text>This fades as you scroll</Text>
</Animated.View>
);
};

Using with RTVScrollView

You must use RTVScrollView instead of the standard ScrollView for collapsible headers to work. RTVScrollView handles scroll synchronization across tabs:

import { RTVScrollView } from 'reanimated-tab-view';

const PostsTab = () => (
<RTVScrollView>
{posts.map((post) => (
<PostCard key={post.id} post={post} />
))}
</RTVScrollView>
);

Using with RTVFlatList

For list-based content, use RTVFlatList instead of FlatList:

import { RTVFlatList } from 'reanimated-tab-view';

const PostsTab = () => (
<RTVFlatList
data={posts}
renderItem={({ item }) => <PostCard post={item} />}
keyExtractor={(item) => item.id}
/>
);

Reducing initial jitter

Pass initialLayout with tabViewHeader dimensions to avoid layout jitter during the first render:

<TabView
initialLayout={{
tabView: { width: screenWidth },
tabViewHeader: { width: screenWidth, height: 200 },
}}
// ...other props
/>

Platform support

Collapsible headers are currently supported on iOS and Android.