4

I am new to React-Native and love it so far. I am trying to create a screen (for the cross-platform app) with a menu icon on top right and when clicked, I want to open a menu, hopefully with react-native-menu to display 'Sign Out' and 'Account' menu options. Having a hard time figuring out how to invoke the menu after this. Appreciate any help.

 import React, { Component } from 'react';
 import {
       AppRegistry,
       StyleSheet,
       View, 
 } from 'react-native';
 import ActionBar from 'react-native-action-bar';


export test class Main extends Component {

render() {

    return (
            <View style={styles.screen}>
            <ActionBar
            containerStyle={styles.bar}
            backgroundColor='#33cc33'
            rightIcons={[
                         {
                         name: 'menu',
                         onPress: () => console.log('menu clicked'),
                         },
                         ]}
             />
            </View>



                               );
   }
   }


 const styles = StyleSheet.create({
                             screen: {
                             backgroundColor: '#33cc33',
                             flex: 1,
                             paddingTop: 10,
                             alignItems: 'center',
                             //padding: 10
                             },

                             });

AppRegistry.registerComponent('Main', () => Main);
rahul singh Chauhan
  • 323
  • 1
  • 4
  • 15
CNK2343
  • 169
  • 2
  • 3
  • 11
  • Hi, i use [this library](https://github.com/react-native-community/react-native-drawer-layout) for create component menu on `ReactNative`. Maybe you can try too. – manggaraaaa Aug 02 '17 at 04:28

3 Answers3

8

I try to complete with your case, i add library react-native-drawer-layout for create menu drawer layout . You can find in this for installation.

Step 1 - Create menu list (I created a separate to make it easier when I want to add another menu), It's content only ArrayList. I called that file Constants, and you can write in Constants.js like :

export const MENU_LIST = [
  { index: 1, name: 'Action' },
  { index: 2, name: 'Sign Out' },
]

Step 2 - I create Menu component for showing menu list. In Menu.js you write like :

import React, { Component } from 'react';
import { View, ScrollView, Text, TouchableOpacity } from 'react-native';

const menuList = require('./Constants.js');

export default class Menu extends Component {
  render() {
    return (
      <View style={{ flex:1, backgroundColor: '#33cc33'}}>
        <ScrollView>
          {menuList.MENU_LIST.map(item => (
            <TouchableOpacity
              key={item.index}
              onPress={() => console.log('entered menu')}
            >
              <Text style={{color: 'white', fontSize: 16, paddingLeft: 20, paddingTop: 16}}>{item.name}</Text>
            </TouchableOpacity>
          ))}
        </ScrollView>
      </View>
    );
  }
}

Step 3 - Refactor main component like :

import React, { Component } from 'react';
import { AppRegistry, StyleSheet, View } from 'react-native';
import ActionBar from 'react-native-action-bar';
import DrawerLayout from 'react-native-drawer-layout';

import Menu from './Menu';

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      drawerClosed: true,
    };
    this.toggleDrawer = this.toggleDrawer.bind(this);
    this.setDrawerState = this.setDrawerState.bind(this);
  }

  setDrawerState() {
    this.setState({
      drawerClosed: !this.state.drawerClosed,
    });
  }

  toggleDrawer = () => {
    if (this.state.drawerClosed) {
      this.DRAWER.openDrawer();
    } else {
      this.DRAWER.closeDrawer();
    }
  }

  render() {
    return (
      <DrawerLayout
        drawerWidth={300}
        ref={drawerElement => {
          this.DRAWER = drawerElement;
        }}
        drawerPosition={DrawerLayout.positions.left}
        onDrawerOpen={this.setDrawerState}
        onDrawerClose={this.setDrawerState}
        renderNavigationView={() => <Menu />}
      >
        <ActionBar
          containerStyle={styles.bar}
          backgroundColor="#33cc33"
          leftIconName={'menu'}
          onLeftPress={this.toggleDrawer}/>

      </DrawerLayout>
    );
  }
}

const styles = StyleSheet.create({
  screen: {
    backgroundColor: '#33cc33',
    flex: 1,
    paddingTop: 10,
    alignItems: 'center',
    //padding: 10
  },
});

AppRegistry.registerComponent('Main', () => App);

In my emulator, that will display like:

enter image description here

and when i klik menu icon, that will display like:

enter image description here

UPDATE-1 :

if you want to make component drawer menu not fills up to bottom, you can play on style in component <Menu />, i give margin for wrapper like:

const styles = StyleSheet.create({
  wrapper: {
    backgroundColor: '#33cc33',
    marginTop: 50,

  },

  listMenu: {
    color: 'white', 
    fontSize: 16, 
    paddingLeft: 20, 
    paddingTop: 12,
    paddingBottom: 12,
  }

});

And add style to component in <Menu /> like :

export default class Menu extends Component {
  render() {
    return (
      <View style={styles.wrapper}> //add style wrapper
        <ScrollView>
          {menuList.MENU_LIST.map(item => (
            <TouchableOpacity
              key={item.index}
              onPress={() => console.log('entered menu')}
            >
              <Text style={styles.listMenu}>{item.name}</Text> //add style menu
            </TouchableOpacity>
          ))}
        </ScrollView>
      </View>
    );
  }
}

Full code in Menu.js like :

import React, { Component, PropTypes } from 'react';
import { View, ScrollView, Text, TouchableOpacity, Image, StyleSheet } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';

const menuList = require('./Constants.js');

export default class Menu extends Component {
  render() {
    return (
      <View style={styles.wrapper}>
        <ScrollView>
          {menuList.MENU_LIST.map(item => (
            <TouchableOpacity
              key={item.index}
              onPress={() => console.log('entered menu')}
            >
              <Text style={styles.listMenu}>{item.name}</Text>
            </TouchableOpacity>
          ))}
        </ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  wrapper: {
    backgroundColor: '#33cc33',
    marginTop: 50,

  },

  listMenu: {
    color: 'white', 
    fontSize: 16, 
    paddingLeft: 20, 
    paddingTop: 12,
    paddingBottom: 12,
  }

});

And the result like :

enter image description here


UPDATE-2 :

based on your case in the comments, if you want to change position menu to the right. You must change position the drawer first.

Actually :

  • i set drawer half the screen and postion in the left. You can see in main file like :

 render() {
    return (
      <DrawerLayout
       
        /* This for set width drawer */
        
        drawerWidth={300}

        /* end */

        ref={drawerElement => {
          this.DRAWER = drawerElement;
        }}

        /* This for set position drawer */

        drawerPosition={DrawerLayout.positions.left}

        /* end */

        onDrawerOpen={this.setDrawerState}
        onDrawerClose={this.setDrawerState}
        renderNavigationView={() => <Menu />}
      >
        <ActionBar
          containerStyle={styles.bar}
          backgroundColor="#33cc33"
          leftIconName={'menu'}
          onLeftPress={this.toggleDrawer}
          
        />

      </DrawerLayout>
    );
  }

Hopelly :

  • i set the menu options on the right. You just change position drawer like :

 render() {
    return (
      <DrawerLayout
        drawerWidth={300}
        ref={drawerElement => {
          this.DRAWER = drawerElement;
        }}
        
        // i change the position to the right.
        drawerPosition={DrawerLayout.positions.Right}
        
        onDrawerOpen={this.setDrawerState}
        onDrawerClose={this.setDrawerState}
        renderNavigationView={() => <Menu />}
      >
        <ActionBar
          containerStyle={styles.bar}
          backgroundColor="#33cc33"
          rightIcons={[
            {
              name: 'menu',
              onPress: this.toggleDrawer,
            },
          ]}
        />

      </DrawerLayout>
    );
  }

if you want to learn about DrawerLayout on Android you can read the documentation.

for the case, my emulator showing like :

enter image description here


I hope my answer can to help you and give your another idea to develop your apps. fighting... ;))

manggaraaaa
  • 802
  • 1
  • 8
  • 23
  • Thank you very much. Good example! Since drawer fills up top to bottom and doesn't look like a menu, is it possible to use react-native-menu which looks like a nice menu. Appreciate any help. – CNK2343 Aug 02 '17 at 22:33
  • it's possible... But use `react-native-drawer-layout` can too. You just add style for component drawer menu. You can see in my answer, i update it.. – manggaraaaa Aug 03 '17 at 04:02
  • Thanks again. But why can't I have the 'menu' on right ? When I change to right, it disappears. For menu, can I use TouchableHighlight and still pull text from Constants ? – CNK2343 Aug 03 '17 at 17:14
  • yaapz.. because you have to set the drawer. For the first case I set it half the screen and postion in the left. If you want to change to right, you can set it by the right position. I update my answer to show you `react-native-drawer-layout` is worked for create menu options. ;) – manggaraaaa Aug 04 '17 at 04:37
  • This looks great ! Thanks for your help! Is it possible to display icons in the menu instead of text ? And trigger a routine if the icon(s) are clicked ? – CNK2343 Aug 05 '17 at 03:23
  • yaapz.. it's possible. i suggest you to use library [`react-native-vector-icons`](https://github.com/oblador/react-native-vector-icons) for using icon. – manggaraaaa Aug 07 '17 at 10:35
1

i use native-base library to create menu, this is the documentation. you can try to search component you needed

https://docs.nativebase.io/Components.html#Components

this is one example i tried to make a menu

/** * Sample React Native App * https://github.com/facebook/react-native * @flow */

import React, { Component } from 'react';
import { AppRegistry } from 'react-native';
import { Container, Content, Header, Body, Right, Button, Icon, Title, Drawer, Text } from 'native-base';

class SideBar extends Component {
  render(){
    return(
      <Content style={{ backgroundColor: '#FFF' }} >
          <Text>Account</Text>
          <Text>SignOut</Text>
      </Content>
    )
  }
}

export default class App extends Component {
  closeDrawer = () => {
    this.drawer._root.close()
  }
  openDrawer = () => {
    this.drawer._root.open()
  }
  render(){
    return(
      <Drawer
        ref={(ref) => { this.drawer = ref; }}
        content={<SideBar navigator={this.navigator} />}
        onClose={() => this.closeDrawer()} >
          <Container>
            <Header>
              <Body>
                <Title>Header</Title>
              </Body>
              <Right>
                <Button transparent onPress={this.openDrawer} >
                  <Icon name='menu' />
                </Button>
              </Right>
            </Header>
          </Container>
      </Drawer>
    )
  }
}

AppRegistry.registerComponent('Main', () => App);

you can style your own menu. maybe it can help you, thanks :)

Rizal Sidik
  • 979
  • 6
  • 17
0

react-native-modal-dropdown implement these things

+import ModalDropdown from 'react-native-modal-dropdown';
class FooBar extends PureComponent {
     constructor(props) {
         super(props);
+        this.dropdownOptions = [{
+            text: 'Scan',
+            icon: require('../images/scan.png'),
+            onPress: this.toScan,
+        }, {
+            text: 'Share',
+            icon: require('../images/share.png'),
+            onPress: this.toShare,
+        }];


+    adjustDropdownStyle = style => {
+        return {
+            width: 110,
+            height: 96, // calculated from margin and height of renderDropdownItem bellow
+            right: 0,
+            top: style.top,
+        };
+    }
+
+    renderDropdownItem = (item, index, highlighted) => {
+        return (
+            <View style={{alignItems: 'center', flexDirection: 'row'}}>
+                <Image source={item.icon} style={{margin: 10, width: 28, height: 28 }}/>
+                <Text style={{fontSize: 15}}>
+                    {item.text}
+                </Text>
+            </View>
+        );
+    }
+
+    onDropdownSelect = (index, item) => item.onPress()
+
     render() {
        let navs = {
            Center: {
                text: 'Home',
            },
            Right: {
                image: require('../images/more.png'),
+                onPress: () => this.dropdown && this.dropdown.show(),
            },
        };

                  <Header navs={navs}/>
+                <ModalDropdown
+                    ref={view => {this.dropdown = view;}}
+                    style={{height: 0}}
+                    adjustFrame={this.adjustDropdownStyle}
+                    options={this.dropdownOptions}
+                    renderRow={this.renderDropdownItem.bind(this)}
+                    onSelect={this.onDropdownSelect.bind(this)}
+                />
Li Zheng
  • 685
  • 7
  • 11