天天看點

[React Native]DrawerNavigator 抽屜元件

1.首先可以參考官方例子:

​​https://reactnavigation.org/docs/en/drawer-based-navigation.html​​

這個是最簡單的

這個是官方GitHub例子:

​​https://github.com/react-navigation/react-navigation/blob/master/examples/NavigationPlayground/js/Drawer.js​​

當然這個也是比較簡單的,隻是通過openDrawer()來啟動

2.結合tab bar

如果結合tab bar則變複雜了很多,因為我點選drawer裡面的item時要跳轉到對應的tab上,就不能簡單使用openDrawer()來啟動了,而且簡單drawer不會遮擋下面的tab bar.

好在發現了一個女程式員寫的例子,解決了我這個問題:

先給出位址:https://readybytes.in/blog/how-to-integrate-tabs-navigation-drawer-navigation-and-stack-navigation-together-in-react-navigation-v2

gitLab:https://gitlab.com/readybytes/ReactNavigationExampleVersion2

3.我的代碼分析:

export const DrawerStack = createDrawerNavigator({
    HOME: {
      screen: TabNavigator,
    },
},
{
    initialRouteName: 'HOME',
    contentComponent: DrawerScreen,
    contentOptions: {
      activeTintColor: '#e91e63',
    },
    style:{
        backgroundColor: '#dfe04d',
    },
});      

DrawerStack,裡面裝tabNavigation, tabNavigation裡面再裝StackNavigation

裡面用到contentComponent: DrawerScreen,這裡導入了DrawerScreen頁面元件.也就是這個Drawer裡面是一個自定義頁面.還有調整背景在DrawerStack裡面調,進入到DrawerScreen不能調整.

調用:

隻需要在棧中的頁面調用即可,openDrawer()後會使用DrawerScreen

<Button onPress={() => this.props.navigation.openDrawer()} title="Open drawer" />      

我的DrawerScreen:先放效果圖:

[React Native]DrawerNavigator 抽屜元件
import React, {Component} from 'react';
import {NavigationActions} from 'react-navigation';
import PropTypes from 'prop-types';
import {ScrollView, Text, View, StyleSheet, Image, TouchableOpacity} from 'react-native';
import { DrawerActions } from 'react-navigation';
import styles from '../styles/index';

class DrawerScreen extends Component {
  navigateToScreen = (route) => () => {
    const navigateAction = NavigationActions.navigate({
      routeName: route
    });
    this.props.navigation.dispatch(navigateAction);
    this.props.navigation.dispatch(DrawerActions.closeDrawer())
  }

  _cancleDrawer=function() {
      this.props.navigation.closeDrawer()
  }

  render () {
    return (
      <View style={style.rootContainer}>

        <View style={style.head}>
          <Image source={require('../img/menu_header.png')} style={{resizeMode:'contain'}} />
        </View>

        <View style={style.head_bar}>
        <TouchableOpacity onPress={() =>this._cancleDrawer()}>
          <Image source={require('../img/menu_cancle.png')} />
        </TouchableOpacity>
        <Image source={require('../img/menu_inbox.png')} style={style.inboxStyle}/>
          <Text style={{marginTop:10, fontWeight:'bold'}}>INBOX</Text>
        </View>

        <ScrollView>
          <View>

          <TouchableOpacity onPress={this.navigateToScreen('Home')}>
            <View style={styles.menuItem}>
            <Image source={require('../img/menu_home.png')} style={style.listImage}/>
              <Text  style={style.textStyle}>
                Home
              </Text>
            </View>
            </TouchableOpacity>

          <TouchableOpacity onPress={this.navigateToScreen('Schedule')}>
            <View style={styles.menuItem}>
              <Image source={require('../img/menu_schedule.png')} style={style.listImage}/>
              <Text  style={style.textStyle}>
               SCHEDULE
              </Text>
            </View>
            </TouchableOpacity>

          <TouchableOpacity onPress={this.navigateToScreen('Booking')}>
            <View style={styles.menuItem}>
              <Image source={require('../img/menu_booking.png')} style={style.listImage}/>
              <Text  style={style.textStyle}>
              BOOKING
              </Text>
            </View>
            </TouchableOpacity>

            <TouchableOpacity onPress={this.navigateToScreen('Member')}>
            <View style={styles.menuItem}>
              <Image source={require('../img/menu_member.png')} style={style.listImage}/>
              <Text  style={style.textStyle}>
              MEMBER
              </Text>
            </View>
            </TouchableOpacity>

            <TouchableOpacity onPress={this.navigateToScreen('SettingScreen')}>
            <View style={styles.menuItem}>
              <Image source={require('../img/menu_setting.png')} style={style.listImage}/>
              <Text onPress={this.navigateToScreen('SettingScreen')} style={style.textStyle}>
              SETTING
              </Text>
            </View>
            </TouchableOpacity>
            
          </View>
        </ScrollView>
      </View>
    );
  }
}

DrawerScreen.propTypes = {
  navigation: PropTypes.object
};

const style = StyleSheet.create({
  rootContainer:{
    flex: 1,
    flexDirection: 'column'
  },
  head:{
    marginTop: 30,
    alignItems: 'center',
    justifyContent: 'center'
  },
  head_bar:{
    flexDirection: 'row', 
    height:50
  },
  inboxStyle:{
    marginLeft: 120,
  },
  listStyle:{
    flex: 1,
    marginTop:10
  },
  textStyle:{
    marginTop:10,
    marginLeft: 10,
    fontWeight: 'bold',
    textAlign:'center',
  },
  listImage:{
    marginLeft:50
  }
})

export default DrawerScreen;      

 幾個要點:

一.核心實作跳轉到相應的tab:

navigateToScreen = (route) => () => {
    const navigateAction = NavigationActions.navigate({
      routeName: route
    });
    this.props.navigation.dispatch(navigateAction);
    this.props.navigation.dispatch(DrawerActions.closeDrawer())
  }      

二.onPress問題:

有兩種:

如果沒有傳回,調用的是類,則要這樣:

<TouchableOpacity onPress={this.navigateToScreen('Member')}>      

第二種有傳回的時候調用,一般調用的是function:

<TouchableOpacity onPress={() =>this._cancleDrawer()}>      

 (_fooFunc()表示私有)

類寫在() =>中會發現跳轉不了.function寫在onPress={this._cancleDrawer()}會looping錯誤或者其他異常.因為onPress在render中會被渲染,onPress={this._cancleDrawer()}這樣寫會直接執行this的内容.

三.style UI:

flexDirection: 'column'      

這個可以控制控件排列.

注意同級控件如果有一個加了flex,其他即使沒有加flex,也會按照比例排開,是以要注意,不是什麼情況都加flex的.