I have my own Header
component that has a search field and some other features unique to my app. I simply define it on the navigationOptions
for each screen.
SomeScreen.navigationOptions = (props) => ({
header: <Header {... props} />,
});
What I want to do though is animate the title inside the component itself as it moves from screen to screen? In general how can I accomplish this with a custom header? I've looked at the react-navigation-stacks
implementation of Header but I can't make much sense of it.
Depending on your version of stack navigator, you'll need to check the props you receive. First of all, pass a function returning an element to the header option so that you receive the props:
SomeScreen.navigationOptions = {
header: props => <Header {...props} />
};
If you're on react-navigation-stack@2.x
(alpha), you get a prop called scene
. It's an object containing a progress
property which has 3 properties which are reanimated nodes.
current
: represents the progress of the screen that the header, it ranges from 0 to 1, where 0 means the screen is fully hidden, and 1 means the screen is fully shown.next
: similar to current, but for the next screen in the stack. can be undefined
when there's no next screenprevious
: similar to current, but for the previous screen in the stack. can be undefined
when there's no previous screenYou can interpolate on these values to animate your view. For example, say you want to animate the opacity to start from 0.5 and to 1 as screen comes in:
import Animated from "react-native-reanimated";
// ...
<Animated.Text
style={{
opacity: Animated.interpolate(scene.progress.current, {
inputRange: [0, 1],
outputRange: [0.5, 1]
})
}}
/>;
If you're on react-navigation-stack@1.x
, you get a prop called position
. It's an animated node which represents the current position of the stack (ranges from 0 to current index). You can interpolate on it to animate your header. It can be a bit tricky, so you'll have to play around.
For example, say you want to animate the opacity to start from 0.5 and to 1 as screen comes in:
NOTE: I haven't tested this one so the code might be wrong. So you'll have to play around with it.
import { Animated } from "react-native";
// ...
<Animated.Text
style={{
opacity: position.interpolate({
inputRange: [index - 1, index],
outputRange: [0.5, 1]
})
}}
/>;