How to Add a Sticky Header inside ScrollView in React Native
Published On: 2023-12-29
Posted By: Harish
In this post, we will add a sticky header to react native ScrollView which stays on top the screen even on scroll. First create a new react native project.
Create A New Project
Create a new react-native project by using npx. Check documentation for creating a new react native project.
npx react-native@latest init ReactNativeStickyHeaderScrollViewExample
Adding a basic ScrollView
Add ScrollView to app.tsx
. If we use a single parent view, the contents of the view will scroll but if we want a view to stick, we have to add the sticky view outside of the main view.
//app.tsx
<ScrollView
stickyHeaderIndices={[1]}
style={styles.scrollView}
>
<View style={styles.block} />
<View style={styles.header}>
<TextInput
placeholder="Search"
style={styles.search_input}
/>
</View>
{
list.length !== 0
&& list.map(m => {
return item(m)
})
}
</ScrollView>
Here we can see that the search block is outside of list.map (main view) and its index is listed in stickyHeaderIndices
array. For index, think of it as an array of views inside scrollview.
Final output will look like

Complete code,
//app.tsx
import {
Text,
TextInput,
View,
StyleSheet,
ScrollView,
} from "react-native";
export const App = () => {
const list = [...Array(4).keys()].map(m => m);
const item = (i: number) => {
return <View key={i} style={styles.item}>
<Text style={styles.item_text}>
{i}
</Text>
</View>
};
return (
<ScrollView
stickyHeaderIndices={[1]}
style={styles.scrollView}
>
<View style={styles.block} />
<View style={styles.header}>
<TextInput
placeholder="Search"
style={styles.search_input}
/>
</View>
{
list.length !== 0
&& list.map(m => {
return item(m)
})
}
</ScrollView>
);
}
const styles = StyleSheet.create({
scrollView: {
flex: 1,
backgroundColor: 'white'
},
block: {
height: 200,
marginBottom: 10,
backgroundColor: 'tan'
},
header: {
padding: 10,
backgroundColor: 'white'
},
search_input: {
padding: 10,
fontSize: 15,
borderWidth: 1,
borderColor: 'lightgray',
borderRadius: 50,
},
item: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
height: 300,
padding: 10,
borderWidth: 1,
margin: 10,
borderRadius: 10,
borderColor: 'white',
backgroundColor: 'lavender'
},
item_text: {
color: "black",
fontSize: 15,
textAlign: "center",
},
});