Jamie Shepherd
Jamie Shepherd

Reputation: 1169

How to pass navigation props to "createStackNavigator" to use default header with animation

I have been working over the last few days to add an animated header to my screens. I have succeeded in this however I would now like to apply this as my header by default rather then copying and pasting the code into all screens I wish to use it. At the moment the animated header is implemented in the screen as follows:

To render the header:

static navigationOptions = ({ navigation }) => {
    return {
        header: () => {
            return (
                <SafeAreaView style={{
                    height: 0,
                    overflow: 'visible',
                }}>
                    <Animated.View style={{height: 80, width: 80,
                        transform: [ {translateY: navigation.getParam('headerScrollY', 0)}]
                    }}>
                        <TouchableOpacity style={{padding: 20}} onPress={() => navigation.goBack()}>
                            <Icon.Ionicons  style={{color: '#ffffff', width: 50, height: 50}} name={'ios-arrow-round-back'} size={50} />
                        </TouchableOpacity>
                    </Animated.View>
                </SafeAreaView>
            )
        }
    }
};

To setup the state:

constructor() {
    super();
    this.state = {
        headerScrollY: new Animated.Value(0),
    };
}

To set the animation interpolation and pass value to navigation props (this is what I am going to have to access later when rendering the header)

componentWillMount() {
    this.props.navigation.setParams({
        headerScrollY: this.state.headerScrollY.interpolate({
            inputRange: [0, 80],
            outputRange: [0, -80],
        })
    });
}

Main render method with "scrollView" calling "onScroll" event to pick up scrolling action

render() {
    return (
            <ScrollView
                style={Styles.wholePageContainer}
                showsVerticalScrollIndicator={false}
                scrollEventThrottle={16}
                onScroll={Animated.event( [{nativeEvent:{contentOffset: {y: this.state.headerScrollY}}}])}
            >
                ...
            </ScrollView>
        );
    }

To set the default header I must set the "header" value of "defaultNavigationOptions" when I use "createStackNavigator". I am able to use this to create a simple defaultHeader in red with height of 100 (code and image below):

const HomeStack = createStackNavigator({
    Home: HomeScreen,
    Category: CategoryScreen,
    Venue: VenueScreen,
    Activity: ActivityScreen,
}, {
    headerMode: 'screen',
    defaultNavigationOptions: {
        header: <View style={{backgroundColor: '#ff0000', height: 100}} />
        ,
    },
});

Simulator demonstrating application of simple default header

Unfortunately for my animated header I require the "navigation" prop as this is used to store the animation values. I have tried many approaches into passing this to where I need the values and was wondering if anyone knew how to do this or if it is even possible or if anyone had any suggestions.

Upvotes: 4

Views: 2207

Answers (1)

Jamie Shepherd
Jamie Shepherd

Reputation: 1169

Thanks to Hend El-Sahli I have now got the code to work as intended. The result (for future reference for others) is as before however removing the header definitions in the navigation options for each screen and the "createStackNavigator" call is as follows:

const HomeStack = createStackNavigator({
    Home: HomeScreen,
    Category: CategoryScreen,
    Venue: VenueScreen,
    Activity: ActivityScreen,
}, {
    headerMode: 'screen',
    defaultNavigationOptions: ({ navigation }) => ({
        header:
            <SafeAreaView style={{
                height: 0,
                overflow: 'visible',
            }}>
                <Animated.View style={{height: 80, width: 80,
                    transform: [ {translateY: navigation.getParam('headerScrollY', 0)}]
                }}>
                    <TouchableOpacity style={{padding: 20}} onPress={() => navigation.goBack()}>
                        <Icon.Ionicons  style={{color: '#ffffff', width: 50, height: 50}} name={'ios-arrow-round-back'} size={50} />
                    </TouchableOpacity>
                </Animated.View>
            </SafeAreaView>
    }),
});

Upvotes: 6

Related Questions