Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement custom header icons within a (nested) StackNavigator?

Tags:

react-native

This might be a noobish question, but although I read the documentation and other sources, I still did not figure out how to implement two or more additional, clickable icons in the header within a StackNavigator, just like in the picture. If the stackNavigator wants to show a back-icon, he is allowed to overwrite the menu-icon.

This is how the (root) home-screen could look like. Once the user starts clicking on the content, the menu-item should be replaced with the back-button from the stackNavigator (ideally on any platform). Mockup of what I want to achieve.

What I did so far: I started from a brand-new template by choosing the options tabs when running expo init. I did some minor modifications in the file MainTabNavigator.js

import React from 'react';
import { Platform } from 'react-native';
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation';
import CustomHeader from '../components/CustomHeader';
import HomeScreen from '../screens/HomeScreen';    

const HomeStack = createStackNavigator( { Home: HomeScreen }, {
   // default config for screens in the stack, so `Home` will use this title 
  navigationOptions: { 
    title: 'Protype Prompter: Browse',
    header: props => <CustomHeader {...props} />,
    }}
);
// All other code stays like provided by expo init.
export default createBottomTabNavigator({
  HomeStack,
});

Next, I made sure that within HomeScreen.js the header is not overwritten:

export default class HomeScreen extends React.Component {
  /* static navigationOptions = {
    header: null,
  }; */

Please help me to with my CustomHeader.js. All my efforts so far so did not lead to any visible change on the home screen.

import React from "react";
import { Header } from "react-navigation";
import { View, Platform, Image, StyleSheet } from "react-native";
import { SimpleLineIcons } from '@expo/vector-icons'; 
const CustomHeader = props => {
  return (
    <View>
        <SimpleLineIcons name="menu" size={24} color={tintColor} />
         <Header headerLeft={<SimpleLineIcons name="menu" size={24} color='#6a1b9a' />} {...props} />
    </View>
  );
};
export default CustomHeader;

Beside other sources, I consulted so far the following websites:

  1. The documentation on headers and header buttons
  2. A github discussion on a react-navitation issue
  3. A howto on modifying headers and another one on customer headers with react-navigation. The latter seemed to be a good starting point.
like image 400
B--rian Avatar asked Nov 21 '18 12:11

B--rian


People also ask

How do I customize a header in react native?

To configure the header bar of a React Native application, the navigation options are used. The navigation options are a static property of the screen component which is either an object or a function. headerTitle: It is used to set the title of the active screen. headerStyle: It is used to add style to the header bar.


1 Answers

This is pretty easy actually. Considered you are using React Navigation V2 or V3, take a look at the createStackNavigator docs.

There you have a headerLeft and a headerRight setting which can both take a custom component. So you can easily code up your example header.

Edit

So I coded up an example fastly:

In your App.js:

import React, { Component } from "react";
import Navigator from "./navigation/navigation";

export default class App extends Component {
  render() {
    return <Navigator />;
  }
}

navigation.js:

import { createStackNavigator } from "react-navigation";
import HomeScreen from "../screens/HomeScreen";

const RootStack = createStackNavigator({ HomeScreen });

export default RootStack;

Now you can design your header on a screen by screen basis like this:

import React, { Component } from "react";
import { Platform, StyleSheet, Text, View } from "react-native";
import { SafeAreaView } from "react-navigation";
import { Icon } from "react-native-elements";

const styles = StyleSheet.create({
  container: {
    flex: 1
  },
  icon: {
    paddingLeft: 10
  },
  iconContainer: {
    flexDirection: "row",
    justifyContent: "space-evenly",
    width: 120
  }
});

export class HomeScreen extends Component {
  static navigationOptions = {
    title: "Title",
    headerLeft: (
      <Icon
        containerStyle={styles.icon}
        type="ionicon"
        name={Platform.OS === "ios" ? "ios-menu" : "md-menu"}
      />
    ),
    headerRight: (
      <View style={styles.iconContainer}>
        <Icon type="ionicon" name={Platform.OS === "ios" ? "ios-search" : "md-search"} />
        <Icon type="ionicon" name={Platform.OS === "ios" ? "ios-heart" : "md-heart"} />
        <Icon type="ionicon" name={Platform.OS === "ios" ? "ios-more" : "md-more"} />
      </View>
    )
  };

  render() {
    return (
      <SafeAreaView styles={styles.container}>
        <Text>Hi from the HomeScreen.</Text>
      </SafeAreaView>
    );
  }
}

export default HomeScreen;

I used the <Icon /> component from react-native-elements. You can make these icons clickable by giving them an onPress prop.

Here is a screenshot of the result on iOS:

enter image description here

Shameless plug: If you want to know more about React Navigation you might like my tutorial in which I guide you through building an application with production ready navigation settings.

like image 115
J. Hesters Avatar answered Sep 18 '22 14:09

J. Hesters