如何在反应导航中检测抽屉何时打开?

时间:2017-07-15 19:48:53

标签: react-native react-navigation

我在我的应用中使用了react-navigation的DrawerNavigator。我想检测用户何时拖动侧面菜单以便我可以执行某个操作,例如关闭打开的键盘。 我怎样才能做到这一点?我似乎无法在文档中找到解决方案。谢谢。

这是我的代码



import React from 'react';
import { Dimensions } from 'react-native';
import { Icon } from 'react-native-elements';
import { DrawerNavigator, StackNavigator, addNavigationHelpers } from 'react-navigation';


//redux related imports
import { createStore, combineReducers } from 'redux';
import { Provider, connect } from 'react-redux';

import Attendance from './containers/pages/Attendance';
import Fees from './containers/pages/Fees';
import Exams from './containers/pages/Exams';
import InitializeUser from './containers/pages/InitializeUser';
import Landing from './Landing';
import Login from './containers/pages/Login';
import Search from './containers/pages/Search';
import Staff from './containers/pages/Staff';
import Stats from './containers/pages/Stats';
import Students from './containers/pages/Students';
import Verification from './containers/pages/verify';
import ProfileDetail from './components/pages/ProfileDetail';
import FeesDetail from './containers/pages/FeesDetails';


import MainReport from './containers/pages/Reports/Main_Report';
import AcademicDetails from './containers/pages/Reports/Student_Academic_Details';
import { Constants } from './config';
import ResultsLanding from './containers/pages/Reports/ResultsLanding';
import { CustomDrawerContentComponent } from '../src/components/base/SideMenu';


const screenWidth = Dimensions.get('window').width;
const MainPages = DrawerNavigator({
  StudentsPage: {
    path: '/Students',
    screen: Students
  },
  SearchPage: {
    path: '/Seacrh',
    screen: Search
  },

  Staff: {
    path: '/Staff',
    screen: Staff
  },

  Fees: {
    path: '/Fees',
    screen: Fees
  },
  Stats: {
    path: '/Stats',
    screen: Stats
  },
  Results: {
    screen: ResultsLanding,
    navigationOptions: {
      tintColor: 'red',
      flex: 1,
      drawerIcon: ({ tintColor }) => (
        <Icon
          name="content-paste"
          color={tintColor}
        />
      )
    }
  },
  Attendance:
  {
    path: '/Attendance',
    screen: Attendance
  },
},
  {
    initialRouteName: 'StudentsPage',
    contentOptions: {
      activeTintColor: Constants.ui.THEME,
      activeBackgroundColor: 'rgba(0,0,0,0.1)',
      inactiveTintColor: 'rgba(0,0,0,0.6)',
      labelStyle: {
        fontSize: 12,
        marginLeft: 10,
      },
    },

    drawerWidth: screenWidth > 320 ? 300 : 250,
    contentComponent: CustomDrawerContentComponent

  });

export const Navigator = StackNavigator({
  LandingPage: {
    screen: Landing,
    navigationOptions: {
      header: null
    }
  },
  LoginPage: {
    screen: Login,
    navigationOptions: {
      header: null
    },
  },
  ProfileDetailPage: {
    screen: ProfileDetail,
    headerMode: 'screen',
    navigationOptions: {
      header: null
    }
  },
  FeesDetailPage:
  {
    screen: FeesDetail,
    navigationOptions: {
      header: null
    },
  },
  VerifyPage: {
    screen: Verification,
    navigationOptions: {
      header: null
    },
  },
  InitUserPage: {
    screen: InitializeUser,
    navigationOptions: {
      header: null
    },
  },
  MainPages: {
    screen: MainPages,
    navigationOptions: {
      header: null
    }
  },

  MainReportPage: {
    screen: MainReport,
    navigationOptions: {
      header: null
    }
  },
  ExamsMainPage: {
    screen: Exams,
    navigationOptions: {
      header: null
    }
  },
  AcademicDetailsPage: {
    screen: AcademicDetails,
    navigationOptions: {
      header: null
    }
  },

});  

const initialState = MainPages.router.getStateForAction(
  MainPages.router.getActionForPathAndParams('StudentsPage'));  

const navReducer = (state = initialState, action) => {
  const nextState = MainPages.router.getStateForAction(action, state);
  return nextState || state;
}; 

const appReducer = combineReducers({
  nav: navReducer
});

class App extends React.Component {
  componentWillReceiveProps(nextProps) {
    console.warn('nextProps: ', JSON.stringify(nextProps, null, 4));
  }
  render() {
    return (
      <MainPages 
        navigation={addNavigationHelpers({
        dispatch: this.props.dispatch,
        state: this.props.nav,
      })} />
    );
  }
}

const mapStateToProps = (state) => ({
  nav: state.nav
});

const AppWithNavigationState = connect(mapStateToProps)(App);

const store = createStore(appReducer);

class Root extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <AppWithNavigationState />
      </Provider>
    );
  }
}
&#13;
&#13;
&#13;

enter image description here 这是我运行代码时得到的错误的屏幕截图

4 个答案:

答案 0 :(得分:2)

通过遵循指南并修改它以使用DrawerNavigator而不是StackNavigator,我能够检测到DrawerNavigator的打开和关闭侧边菜单操作。这是我在App文件中的内容。在componentWillReceiveProps类的底部附近,我使用import React from 'react'; import { AppRegistry, Image, Text, View, ScrollView } from 'react-native'; import {DrawerNavigator, DrawerItems, addNavigationHelpers } from 'react-navigation'; import { Provider, connect } from 'react-redux' import { createStore, combineReducers } from 'redux' class MyHomeScreen extends React.Component { static navigationOptions = { drawerLabel: 'Home', drawerIcon: ({ tintColor }) => ( <Image source={require('./images/Groups.png')} style={{tintColor: tintColor, width: 26, height: 26}}/> ), }; render() { return ( <View> <Text>Home Screen</Text> </View> ); } } class MyNotificationsScreen extends React.Component { static navigationOptions = { drawerLabel: 'Notifications', drawerIcon: ({ tintColor }) => ( <Image source={require('./images/Events.png')} style={{tintColor: tintColor, width: 26, height: 26}}/> ), }; render() { return ( <View> <Text>Notifications Screen</Text> </View> ); } } const NavDemo = DrawerNavigator({ Home: { screen: MyHomeScreen }, Notifications: { screen: MyNotificationsScreen } }, { tabBarOptions: { activeTintColor: '#e91e63', }, drawerWidth: 200, drawerPosition: 'left', contentComponent: props => <ScrollView><DrawerItems {...props} /></ScrollView> }); const initialState = NavDemo.router.getStateForAction(NavDemo.router.getActionForPathAndParams('Home')); const navReducer = (state = initialState, action) => { const nextState = NavDemo.router.getStateForAction(action, state); return nextState || state; }; const appReducer = combineReducers({ nav: navReducer }); class App extends React.Component { componentWillReceiveProps(nextProps) { console.warn('nextProps: ' + JSON.stringify(nextProps, null, 4)) } render() { return ( <NavDemo navigation={addNavigationHelpers({ dispatch: this.props.dispatch, state: this.props.nav, })} /> ); } } const mapStateToProps = (state) => ({ nav: state.nav }); const AppWithNavigationState = connect(mapStateToProps)(App); const store = createStore(appReducer); class Root extends React.Component { render() { return ( <Provider store={store}> <AppWithNavigationState /> </Provider> ); } } AppRegistry.registerComponent('NavDemo', () => Root); ,每次抽屉打开或关闭时都会显示警告。

nextProps

当我打开抽屉并展开警告nextProps.nav时,如下所示:

Redux Integration

然后在关闭抽屉后,新警告显示如下:

enter image description here

routes是一个包含两个键indexindex的对象。当抽屉打开时,1变为0,当它关闭时,索引变为N

使用该信息,您可以添加if语句,以便在抽屉打开时执行必要的操作。

答案 1 :(得分:1)

这是一个旧线程,但是我想分享我如何做到这一点。

在您的应用程序内(最好是在创建DraweStack的位置)添加以下代码。

const defaultGetStateForAction = DrawerStack.router.getStateForAction;
DrawerStack.router.getStateForAction = (action, state) => {
  switch (action.type) {
    case "Navigation/DRAWER_OPENED":
    case "Navigation/MARK_DRAWER_ACTIVE":
      Keyboard.dismiss();
      break;
  }

  return defaultGetStateForAction(action, state);
};

有各种 action.type 。例如:

  • 在抽屉开始打开时调用Navigation / MARK_DRAWER_ACTIVE
  • 打开抽屉时将调用导航/ MARK_DRAWER_SETTLING。

干杯。

答案 2 :(得分:1)

  • this.props.navigation.state.isDrawerOpen => true / false

答案 3 :(得分:1)

简单来说,如果您使用react-navigation v5-

import { useIsDrawerOpen } from '@react-navigation/drawer'

const isOpen: boolean = useIsDrawerOpen()

然后您必须通过钩子useEffect订阅“ isOpen”标志:

useEffect(() => {
    if (!isOpen) {
      // Your dismiss logic here 
    }
}, [isOpen])

您的自定义抽屉看起来像DrawerContent

希望有帮助