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

问题描述 投票:6回答:2

我在我的应用程序中使用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>
    );
  }
}

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

react-native react-navigation
2个回答
2
投票

通过遵循Redux Integration指南并修改它以使用DrawerNavigator而不是StackNavigator,我能够检测到DrawerNavigator的打开和关闭侧面菜单操作。这是我在index.ios.js文件中的内容。在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看起来像这样:

enter image description here

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

enter image description here

nextProps.nav是一个有两个键的对象,routesindex。当抽屉打开时,index变成1,当它关闭时,索引变成0

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


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.types。例如:

  • 当抽屉开始打开时,将调用Navigation / MARK_DRAWER_ACTIVE
  • 抽屉打开时调用Navigation / MARK_DRAWER_SETTLING。
  • 等等

干杯。

© www.soinside.com 2019 - 2024. All rights reserved.