Adam Katz
Adam Katz

Reputation: 6962

react native programmatically open DrawerLayoutAndroid

I am using the DrawerLayoutAndroid and struggling to work out how to programmatically open and close it.

I see that you are supposed to use

openDrawer(0)but how do you reference the DrawerLayoutAndroid

I have a drawer that I have made exactly like in the docs, then I have a button on my View that if you press it I want it to open the DrawerLayoutAndroid

I created this function

toggleDrawer(){
  openDrawer(0);
};

but that obviously doesnt work, and just throws an error.

Upvotes: 2

Views: 3688

Answers (4)

ankitm
ankitm

Reputation: 195

This is how I implemented it using functional components and React.context:

Create a drawer context:

//DrawerContext.ts

import React from 'react';

export const DrawerContext = React.createContext<{
    isOpen: boolean;
    open: () => void;
    close?: () => void;
}>({
    isOpen: null,
    // close: null,
    open: null,
});

Then in your app:

export const SideMenu: React.FC = (props) => {

    const drawerRef = useRef<DrawerLayoutAndroid>();
    const [drawerIsOpen, setDrawerIsOpen] = useState(false);
 
    useEffect(() => {
        drawerRef.current.openDrawer(); //open drawer when app loads
        setDrawerIsOpen(true);
    }, []);
    return (
            <DrawerLayoutAndroid
                drawerWidth={300}
                renderNavigationView={() => <SideMenuItems />}
                drawerBackgroundColor="rgba(0,0,0,0.5)"
                ref={drawerRef} //get the ref to the drawer
            >
                {/* Pass down the references using the context provider */}
                <DrawerContext.Provider value={{
                    open: () => drawerRef?.current?.openDrawer(),
                    isOpen: drawerIsOpen
                }}>
                    {props.children}
                </DrawerContext.Provider>
            </DrawerLayoutAndroid>
        )
}

And finally, consume the context in any of the children components:

//MyComponent.ts
import {DrawerContext} from './DrawerContext.ts'
...
export const MyComponent: React.FC = (props) => {
    const { open, isOpen, } = useContext(DrawerContext);
    return(
        ...
        <Button onPress={open}>Open Drawer!!</Button>
        ...
    )

}

Upvotes: 0

Syed Zain Ali
Syed Zain Ali

Reputation: 1226

you have to Use   

ref={_drawer => (this.drawer = _drawer)}

import React, { Component } from "react";
import {
  Text,
  View,
  DrawerLayoutAndroid,
  TouchableHighlight
} from "react-native";
export default class DrawerExample extends Component {

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

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

  render() {
    var navigationView = (
      <View style={{ flex: 1, backgroundColor: "#fff" }}>
        <Text style={{ margin: 10, fontSize: 15, textAlign: "left" }}>
          I'm in the Drawer!
        </Text>
      </View>
    );
    return (
      <DrawerLayoutAndroid
        drawerWidth={300}
        ref={_drawer => (this.drawer = _drawer)}
        drawerPosition={DrawerLayoutAndroid.positions.Left}
        renderNavigationView={() => navigationView}
      >
        <View style={{ flex: 1, alignItems: "center" }}>
          <Text style={{ margin: 10, fontSize: 15, textAlign: "right" }}>
            Hello
          </Text>
          <Text style={{ margin: 10, fontSize: 15, textAlign: "right" }}>
            World!
          </Text>
          <TouchableHighlight onPress={this.openDrawer}>
            <Text>{"Open Drawer"}</Text>
          </TouchableHighlight>
        </View>
      </DrawerLayoutAndroid>
    );
  }
}

Upvotes: 4

Manuel Torre
Manuel Torre

Reputation: 77

If you have to open it programmatically from a component (a View, for example) that is INSIDE the drawerlayoutandroid, you will need to call the function openDrawer() but with ".bind(this)". Otherwise, you won't be able to make it work, even using refs (that you will need to use anyway, as Jagadish wrote). I had that problem for a few days till I found out what I just wrote. Hope it helps.

Upvotes: 2

Jagadish Upadhyay
Jagadish Upadhyay

Reputation: 1264

You should use refs for this. I am pasting the example here for your reference

    var DrawerExample = React.createClass({

        openDrawer:function() {
            this.refs['myDrawer'].openDrawer();
        },

        closeDrawer:function() {
            this.refs['myDrawer'].closeDrawer();
        },

        render: function() {
            var navigationView = (
                <View style={{flex: 1, backgroundColor: '#fff'}}>
                    <Text style={{margin: 10, fontSize: 15, textAlign: 'left'}}>I'm in the Drawer!</Text>

                    <TouchableHighlight onPress={this.closeDrawer}>
                        <Text>{'Close Drawer'}</Text>
                    </TouchableHighlight>

                </View>
            );
            return (
                <DrawerLayoutAndroid ref="myDrawer"
                    drawerWidth={300}
                    drawerPosition={DrawerLayoutAndroid.positions.Left}
                    renderNavigationView={() => navigationView}>
                    <View style={{flex: 1, alignItems: 'center'}}>
                        <Text style={{margin: 10, fontSize: 15, textAlign: 'right'}}>Hello</Text>
                        <Text style={{margin: 10, fontSize: 15, textAlign: 'right'}}>World!</Text>

                        <TouchableHighlight onPress={this.openDrawer}>
                            <Text>{'Open Drawer'}</Text>
                        </TouchableHighlight>

                    </View>
                </DrawerLayoutAndroid>
            );
        },
    });

Upvotes: 8

Related Questions