Animated Header in React Native

Aditya Singh
3 min readNov 11, 2018

--

Lets animate that boring header in your react native app.

I have also put up a video regarding this. Skip it, if you prefer reading.

First things first, lets create a basic App.js file and route it to another component which we will call Main.js. Also, we add our own custom Header.js to our app.

import React from 'react';
import { createStackNavigator } from "react-navigation";
import Main from "./Main";
import Header from "./Header";
const MainStack = createStackNavigator({
Main: {
screen: Main,
navigationOptions: ({ navigation, screenProps }) => {
return {
header: <Header {...navigation} {...screenProps} />
};
}
}
});
export default class App extends React.Component {
render() {
return <MainStack />;
}
}

Now, we need to animate the height of our header based on the amount of scroll a user does. To do that, we need to take an input from our Main.js component and pass it to our header component.

We are going to use a ScrollView and it’s onScroll event.

The onScroll event will give us the amount of scroll a user does while inside ScrollView. From the onScroll event, we get the yOffset value which we use to change the height of our header. Next, we assign it to this.scrollY which is variable that we interpolate. We are going to use this value, modify (interpolate) it and then pass it to our Header.js component using React Navigation’s

this.props.navigation.setParams({ paramName: paramValue })

Our final Main.js file should look like so.

import React from "react";
import { View, Text, ScrollView, Animated } from "react-native";
export default class Main extends React.Component { componentDidMount() {
this.scrollY = new Animated.Value(0);
this.changingHeight = this.scrollY.interpolate({
inputRange: [0, 50],
outputRange: [120, 60],
extrapolate: "clamp"
});
this.props.navigation.setParams({
changingHeight: this.changingHeight
});
}
render() {
return (
<View style={{ flex: 1 }}>
<ScrollView
style={{ height: 1000 }}
scrollEventThrottle={16}
onScroll = { Animated.event([
{
nativeEvent: {
contentOffset: {
y: this.scrollY
}
}
}
])}
>
<View style={{ height: 120 }} />
<Text>Batman Forever!</Text>
</ScrollView>
</View>
);
}
}

scrollEventThrottle is a prop that allows us to set how frequently we receive onScroll events from the user. A larger value will result in a good performance but will output lesser events whereas a smaller value will give us more frequent events but will come at a cost of poor performance.

It is now time to start writing our Header.js component.

We should position our header absolutely, otherwise we will see a jerky animation.

import React from "react";
import { View, Animated, Image } from "react-native";
export default class Header extends React.Component {
render() {
let { params } = this.props.state;
return (
<Animated.View
style={{
height:
params !== undefined &&
params.changingHeight !== undefined
? params.changingHeight
: 120,
position: "absolute",
top: 0,
left: 0,
backgroundColor: "#fff",
width: "100%",
justifyContent: "center",
alignItems: "center"
}}
>
<Text>Custom header</Text>
</Animated.View>
);
}}

Here is a Snack for the same!

There it is, a custom animated header component using Animated API from React Native.

I work as a Javascript developer at Morfsys. I love writing about technology, science and more.

Follow me for more interesting stories.

--

--