在 ToolbarAndroid 上点击图标显示 DrawerLayoutAndroid

18
我刚开始接触 React Native(和 React),并且正在尝试一些操作。
我成功地添加了一个 DrawerLayout,可以从屏幕左侧拖动它。但是,我想在我的 ToolbarAndroid 上单击菜单图标时打开它。
我尝试使用“refs”,但似乎不起作用。
希望我表述清楚了。
谢谢。
5个回答

32

你应该像你提到的那样使用"refs"。为此,对于你的抽屉组件,请设置 "ref" 属性:

<DrawerLayoutAndroid
   ...
   ref={'DRAWER_REF'}
   ...
/>

然后在您的组件中使用this.refs来访问它,并在该引用上调用openDrawercloseDrawer(例如,您可能希望有一个Touchable元素来触发此调用):

this.refs['DRAWER_REF'].openDrawer();

它似乎不起作用,但我猜是因为在该组件上没有访问 this.refs。我的组件嵌套如下:DrawerLayoutAndroid > Navigator(它们渲染一个场景),包括一个 ToolbarAndroid,在其中我正在尝试 onIconClicked={this.refs['DRAWER_REF'].openDrawer()}。 - Maslow
2
this.refs['DRAWER_REF'] 只能从渲染抽屉的组件中访问。如果您想从视图层次结构下的某个组件访问它,则需要将 ref 作为属性向下传递,或者将回调方法作为属性向下传递,并在抽屉父组件级别上定义。 - kzzzf
4
我正在遇到一个问题:“undefined不是对象(在评估'this.refs['DRAWER_REF']'时)”。 - John
1
我认为我们中的许多人都尝试过这个,并得到了“未定义对象”错误。有人能否展示一下关于此的相当完整的代码? - Fadils
抽屉在我的模拟器中平稳地打开,但在我的移动设备上似乎无法正常工作,需要一段时间才能打开抽屉。 - Sumit Kushwaha
显示剩余2条评论

8
使用ReactNative示例,您可以像这样做:
var DrawerTest = React.createClass({
  openDrawer:function() {
    this.refs['DRAWER'].openDrawer()
  },
  render: function() {
    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'}
              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>
    );

  }
});

Full File Gist


2

"undefined is not an object" - 大多数人都会因为上述问题而进入此处。

请确保您已正确使用如下所述的ES6语法。

错误的语法:

onPress={this.drawer()}

正确的语法:

onPress={() => this.drawer()}

代码:

<DrawerLayoutAndroid
   ...
   ref={'DRAWER_REF'}
   ...
/>

--------------------------------------------------

//Write this just before render() method

drawer = () => {
  this.refs['DRAWER_REF'].openDrawer();
}

--------------------------------------------------

<TouchableHighlight onPress={() => this.drawer()}>
   <Icon name="bars" size={30} color="#900"/>
</TouchableHighlight>

2

我想再提供另一种解决方案,特别是当使用 Navigator 渲染场景时。

如果是这种情况,上面的解决方案将无法工作,因为它无法访问 DrawerLayoutAndroid 中指定的 ref,实际上会返回

"undefined is not an object (evaluating 'this.refs['DRAWER_REF']')"

或类似的东西。

解决方案:

创建我们自己的工具栏,以便我们可以将我们的渲染组件传递给它。

MyToolbar.js

... import stuff ...

module.exports = React.createClass({
  render: function() {
    return (
      <ToolbarAndroid
        title={this.props.title}
        navIcon = {{uri: "ic_menu_white_24dp", isStatic: true}}
        style = {styles.toolbar}
        titleColor='#FFFFFF'
        onIconClicked={this._onIconClicked}/>
    );
  },

  _onIconClicked: function(){
    this.props.sidebarRef.refs['DRAWER'].openDrawer();
    // sidebarRef is the rendering component we're passing
  }
});

OpenDrawerFromToolbar.js

...
module.exports = React.createClass({
  render: function() {
    var navigationView = (
      <View style={{flex: 1, backgroundColor: '#fff'}}>
        <Text style={{margin: 10, fontSize: 15, textAlign: 'left'}}>In the Drawer!</Text>
      </View>
    );

    return (
      <View style={styles.container}>
        <DrawerLayoutAndroid drawerWidth = {300}
                         drawerPosition = {DrawerLayoutAndroid.positions.Left}
                         renderNavigationView = {() => navigationView}
                         ref={'DRAWER'}>
        <MyToolbar style={styles.toolbar}
                   title={'My Awesome App'}
                   navigator={this.props.navigator}
                   sidebarRef={this}/> // pass the component to MyToolbar
        <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>
        </View>
      </DrawerLayoutAndroid>
    </View>
  );
  },

  _setDrawer: function() {
    this.refs['DRAWER'].openDrawer();
  }
});

然后我们的导航器组件及其渲染场景函数将起作用:
module.exports = React.createClass({
  render: function() {
    return (
      <Navigator
        style = {styles.container}
        initialRoute = {{ name: 'openDrawerFromToolbar', index: 0 }}
        renderScene = {this.navigatorRenderScene}
        configureScene={ () => { return Navigator.SceneConfigs.PushFromRight; }}/>
  );
},

navigatorRenderScene: function(route, navigator) {
  _navigator = navigator;
      return (
          <OpenDrawerFromToolbar
            route={route}
            navigator={navigator}
            data={route.data}/>
      );
  }
});

0

按照所有这些片段,仍然出现undefined is not an object错误。

然后在GitHub上找到了这个线程,最终解决了我的问题,并完美地解释了refs的问题。

要遵循React Native文档(http://facebook.github.io/react-native/docs/drawerlayoutandroid.html)中的DrawerLayoutAndroid示例,这是可行的代码:

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>
  );
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接