React Native – ToolbarAndroid Drawer Navigation

I will explain my method for using ToolbarAndroid (actually i’m using the wrapper from react-native-vector-icons) to navigate to different screens. I will explain ToolbarAndroid drawer navigation using React Navigator’s stack navigator.

react native stack navigator example

ToolbarAndroid Drawer Navigation with Stack Navigator

Create a new React Native project using this command:

react-native init ToolbarAndroidNavigation

Create a new folder inside named src. We will group our components here.

Install the required dependencies for the Icon.ToolbarAndroid wrapper. This step is optional. The tutorial should work with the default ToolbarAndroid from ‘react-native’, but I like this one because I can easily supply icons.

npm install --save react-native-vector-icons


Don't forget to link this library.

react-native link

Let’s create our home screen. From here we will navigate to other screens.

import React, {Component} from 'react';
import {StyleSheet, View, Text, StatusBar} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';

class Home extends Component {
    render() {
        return (
            <View>
                <StatusBar backgroundColor="#0a254b" barStyle="light-content"/>
                <Icon.ToolbarAndroid style={styles.toolbar} title="MyApp" titleColor="white"
                navIconName="md-menu"
                actions={[
                    { title: 'Settings', iconName: 'md-settings', iconSize: 30, show: 'always' },
                    { title: 'About', iconName: 'md-help', iconSize:30, show: 'never' },
                ]}
                overflowIconName="md-more"
                />
                <Text>Home screen...</Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    toolbar: {
        backgroundColor: '#0d356d',
        height: 56
    }
});

export default Home;

Modify App.js to look like this

import React, {Component} from 'react';
import Home from './src/Home';

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

You should have something like this if you run react-native run-android.

react native stack navigator example

Toolbar drawer navigation requires a toolbar and a drawer, so we’re going to add the drawer and some style to it.

import React, {Component} from 'react';
import {StyleSheet, View, Text, StatusBar, TouchableOpacity} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';

class Home extends Component {
    render() {
        var drawer = (
            <View style={styles.drawer}>
              <View style={styles.temp}>
                <TouchableOpacity>
                  <Text>Settings</Text>
                </TouchableOpacity>
                <TouchableOpacity>
                  <Text>Help</Text>
                </TouchableOpacity>
              </View>
            </View>
        );

        return (
            <View>
                <StatusBar backgroundColor="#0a254b" barStyle="light-content"/>
                <Icon.ToolbarAndroid style={styles.toolbar} title="MyApp" titleColor="white"
                navIconName="md-menu"
                actions={[
                    { title: 'Settings', iconName: 'md-settings', iconSize: 30, show: 'always' },
                    { title: 'About', iconName: 'md-help', iconSize:30, show: 'never' },
                ]}
                overflowIconName="md-more"
                />
                <Text>Home screen...</Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    toolbar: {
        backgroundColor: '#0d356d',
        height: 56
    },
    drawer: {
        flex: 1,
        backgroundColor: '#f1f1f1'
    },
    temp: {
        flexDirection: 'row',
        width: 200,
        justifyContent: 'space-around'
    }
});

export default Home;

Good. Now to use the drawer we need to wrap our stuff inside a DrawerLayoutAndroid instead of a simple View.

Import DrawerLayoutAndroid from ‘react-native’.

import {StyleSheet, View, Text, StatusBar, TouchableOpacity, DrawerLayoutAndroid, Alert} from 'react-native';

Replace View with DrawerLayoutAndroid. Pay attention we added some attributes to this wrapper.

  • renderNavigationView wants a function that returns the object responsible for drawing the view (the drawer).
  • ref is a convenience trick that allows us to have an instance in our class of the current drawer in the view. We need to have a handle on the drawer to open and close it programatically.
return (
            <DrawerLayoutAndroid renderNavigationView={() => drawer} drawerWidth={300} ref={_drawer => (this.drawer = _drawer)}>
                <StatusBar backgroundColor="#0a254b" barStyle="light-content"/>
                <Icon.ToolbarAndroid style={styles.toolbar} title="MyApp" titleColor="white"
                navIconName="md-menu"
                actions={[
                    { title: 'Settings', iconName: 'md-settings', iconSize: 30, show: 'always' },
                    { title: 'About', iconName: 'md-help', iconSize:30, show: 'never' },
                ]}
                overflowIconName="md-more" onIconClicked={this.openDrawer} onActionSelected={this.onToolbarIconClick}
                />
                <Text>Home screen...</Text>
            </DrawerLayoutAndroid>
        );

Add onIconClicked={this.openDrawer} property and function to the toolbar. This defines what will happen when the user presses the toolbar icon (navIconName).

Add this function as well outside the render method.

openDrawer() {
        this.drawer.openDrawer();
    }

But how this.drawer works? It’s not defined anywhere in the class! Well from from ref above.

Only that for effectively using it as a handle for our drawer but we need to bind it in constructor.

constructor() {
        super();
        this.openDrawer = this.openDrawer.bind(this);
    }

Check. We have a functioning drawer!

Lets make toolbar icons work.

Add onActionSelected={this.onToolbarIconClick} to the Icon.ToolbarAndroid tag.

onToolbarIconClick(position) {
        if (position === 0) {
          Alert.alert('Warning', 'You pressed settings')
        } else if (position === 1) {
          Alert.alert('Warning', 'You pressed help');
        }
    }

Don’t forget to import import {StyleSheet, View, Text, StatusBar, TouchableOpacity, DrawerLayoutAndroid, Alert} from ‘react-native’;

Bind in constructor this.onToolbarIconClick = this.onToolbarIconClick.bind(this);

Test it it works..

Create other screen Settings necessary for our ToolbarAndroid drawer navigation.

import React, {Component} from 'react';
import {StyleSheet, View, Text, StatusBar, Alert} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';

class Settings extends Component {
    
    constructor() {
        super();
        this.onToolbarIconClick = this.onToolbarIconClick.bind(this);
    }

    onToolbarIconClick(position) {
        if (position === 0) {
          Alert.alert('Warning', 'You pressed settings')
        } else if (position === 1) {
          Alert.alert('Warning', 'You pressed help');
        }
    }

    render() {
        return (
            <View>
                <StatusBar backgroundColor="#c62726" barStyle="light-content"/>
                <Icon.ToolbarAndroid style={styles.toolbar} title="Settings" titleColor="white"
                navIconName="md-arrow-back"
                actions={[
                    { title: 'Settings', iconName: 'md-settings', iconSize: 30, show: 'always' },
                    { title: 'About', iconName: 'md-help', iconSize:30, show: 'never' },
                ]}
                overflowIconName="md-more" onActionSelected={this.onToolbarIconClick}
                />
                <Text>Settings screen...</Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    toolbar: {
        backgroundColor: '#db4b3f',
        height: 56
    }
});

export default Settings;

react native stack navigator example

But how can we reach this screen from the other?? We use React Navigation! First install:

npm install --save react-navigation
npm install --save react-native-gesture-handler

react-native link

Create new file Navigation.js. This will be responsible for all the ToolbarAndroid drawer navigation throughout our app.

import { createStackNavigator, createAppContainer } from 'react-navigation';
import Home from './Home';
import Settings from './Settings';

const Navigation = createStackNavigator({
    HomeScreen: {screen: Home},
    SettingsScreen: {screen: Settings}
}, {
    initialRouteName: 'HomeScreen',
    headerMode: 'none'
});

export default createAppContainer(Navigation);

Edit App.js.
[/javascript] import React, {Component} from ‘react’;
import Navigation from ‘./src/Navigation’;

export default class App extends Component {
render() {
return (

);
}
}
[/javascript]

Edit drawer as this in Home.js:

var drawer = (
            <View style={styles.drawer}>
              <View style={styles.temp}>
                <TouchableOpacity onPress={() => {this.drawer.closeDrawer(); this.props.navigation.navigate('SettingsScreen')}}>
                  <Text>Settings</Text>
                </TouchableOpacity>
                <TouchableOpacity>
                  <Text>Help</Text>
                </TouchableOpacity>
              </View>
            </View>
        );

Go to Settings.js and add action for going back to previous screen. Of course you can navigate to other screen there instead of back…

<View>
                <StatusBar backgroundColor="#c62726" barStyle="light-content"/>
                <Icon.ToolbarAndroid style={styles.toolbar} title="MyApp" titleColor="white"
                navIconName="md-arrow-back"
                actions={[
                    { title: 'Settings', iconName: 'md-settings', iconSize: 30, show: 'always' },
                    { title: 'About', iconName: 'md-help', iconSize:30, show: 'never' },
                ]}
                overflowIconName="md-more" onIconClicked={this.props.navigation.goBack} onActionSelected={this.onToolbarIconClick}
                />
                <Text>Settings screen...</Text>
            </View>

Now it works!

We can edit the toolbar icons to have them do some worthy actions.

Go to Home.js

onToolbarIconClick(position) {
        if (position === 0) {
            this.props.navigation.navigate('SettingsScreen');
        } else if (position === 1) {
          Alert.alert('Warning', 'You pressed help');
        }
    }

Since this was a long tutorial and might be confusing to understand, here are the full sources for the ToolbarAndroid drawer navigation:

App.js
import React, {Component} from 'react';
import Navigation from './src/Navigation';

export default class App extends Component {
  render() {
    return (
      <Navigation/>
    );
  }
}
Spoiler title
import React, {Component} from 'react';
import {StyleSheet, View, Text, StatusBar, TouchableOpacity, DrawerLayoutAndroid, Alert} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';

class Home extends Component {
    
    constructor() {
        super();
        this.openDrawer = this.openDrawer.bind(this);
        this.onToolbarIconClick = this.onToolbarIconClick.bind(this);
    }

    openDrawer() {
        this.drawer.openDrawer();
    }

    onToolbarIconClick(position) {
        if (position === 0) {
            this.props.navigation.navigate('SettingsScreen');
        } else if (position === 1) {
          Alert.alert('Warning', 'You pressed help');
        }
    }

    render() {
        var drawer = (
            <View style={styles.drawer}>
              <View style={styles.temp}>
                <TouchableOpacity onPress={() => {this.drawer.closeDrawer(); this.props.navigation.navigate('SettingsScreen')}}>
                  <Text>Settings</Text>
                </TouchableOpacity>
                <TouchableOpacity>
                  <Text>Help</Text>
                </TouchableOpacity>
              </View>
            </View>
        );

        return (
            <DrawerLayoutAndroid renderNavigationView={() => drawer} drawerWidth={300} ref={_drawer => (this.drawer = _drawer)}>
                <StatusBar backgroundColor="#0a254b" barStyle="light-content"/>
                <Icon.ToolbarAndroid style={styles.toolbar} title="MyApp" titleColor="white"
                navIconName="md-menu"
                actions={[
                    { title: 'Settings', iconName: 'md-settings', iconSize: 30, show: 'always' },
                    { title: 'About', iconName: 'md-help', iconSize:30, show: 'never' },
                ]}
                overflowIconName="md-more" onIconClicked={this.openDrawer} onActionSelected={this.onToolbarIconClick}
                />
                <Text>Home screen...</Text>
            </DrawerLayoutAndroid>
        );
    }
}

const styles = StyleSheet.create({
    toolbar: {
        backgroundColor: '#0d356d',
        height: 56
    },
    drawer: {
        flex: 1,
        backgroundColor: '#f1f1f1'
    },
    temp: {
        flexDirection: 'row',
        width: 200,
        justifyContent: 'space-around'
    }
});

export default Home;
Settings.js
import React, {Component} from 'react';
import {StyleSheet, View, Text, StatusBar, Alert} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';

class Settings extends Component {
    
    constructor() {
        super();
        this.onToolbarIconClick = this.onToolbarIconClick.bind(this);
    }

    onToolbarIconClick(position) {
        if (position === 0) {
            this.props.navigation.navigate('SettingsScreen');
        } else if (position === 1) {
          Alert.alert('Warning', 'You pressed help');
        }
    }

    render() {
        return (
            <View>
                <StatusBar backgroundColor="#c62726" barStyle="light-content"/>
                <Icon.ToolbarAndroid style={styles.toolbar} title="Settings" titleColor="white"
                navIconName="md-arrow-back"
                actions={[
                    { title: 'Settings', iconName: 'md-settings', iconSize: 30, show: 'always' },
                    { title: 'About', iconName: 'md-help', iconSize:30, show: 'never' },
                ]}
                overflowIconName="md-more" onIconClicked={this.props.navigation.goBack} onActionSelected={this.onToolbarIconClick}
                />
                <Text>Settings screen...</Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    toolbar: {
        backgroundColor: '#db4b3f',
        height: 56
    }
});

export default Settings;
Navigation.js
import { createStackNavigator, createAppContainer } from 'react-navigation';
import Home from './Home';
import Settings from './Settings';

const Navigation = createStackNavigator({
    HomeScreen: {screen: Home},
    SettingsScreen: {screen: Settings}
}, {
    initialRouteName: 'HomeScreen',
    headerMode: 'none'
});

export default createAppContainer(Navigation);
FacebookTwitterLinkedin