React Navigation抽屉的状态? (开放或关闭)

时间:2017-06-15 18:57:55

标签: reactjs react-navigation

我正在使用React Navigation构建抽屉,并且如果用户关闭抽屉,则想要执行某些逻辑。我没有在文档中看到任何可以让我这样做的明显内容。有人知道这样做的方法吗?

12 个答案:

答案 0 :(得分:11)

您需要自定义导航操作才能捕获DrawerClose事件:

const MyDrawerNavigator = DrawerNavigator({
    //...
});

const defaultGetStateForAction = MyDrawerNavigator.router.getStateForAction;

MyDrawerNavigator.router.getStateForAction = (action, state) => {

    //use 'DrawerOpen' to capture drawer open event
    if (state && action.type === 'Navigation/NAVIGATE' && action.routeName === 'DrawerClose') {
        console.log('DrawerClose');
        //write the code you want to deal with 'DrawerClose' event
    }
    return defaultGetStateForAction(action, state);
};

答案 1 :(得分:6)

根据@ufxmeng

import {
  StatusBar,
} from "react-native";

const MyDrawerNavigator = DrawerNavigator({
    //...
});

const defaultGetStateForAction = MyDrawerNavigator.router.getStateForAction;

MyDrawerNavigator.router.getStateForAction = (action, state) => {
    if(state && action.type === 'Navigation/NAVIGATE' && action.routeName === 'DrawerClose') {
        StatusBar.setHidden(false);
    }

    if(state && action.type === 'Navigation/NAVIGATE' && action.routeName === 'DrawerOpen') {
        StatusBar.setHidden(true);
    }


    return defaultGetStateForAction(action, state);
};

点击此处https://github.com/react-community/react-navigation/blob/673b9d2877d7e84fbfbe2928305ead7e51b04835/docs/api/routers/Routers.md 在这里https://github.com/aksonov/react-native-router-flux/issues/699

答案 2 :(得分:3)

这适用于使用react-navigation v2.0 +版本的任何人。现在,您可以跟踪抽屉操作。

{
  OPEN_DRAWER: 'Navigation/OPEN_DRAWER',
  CLOSE_DRAWER: 'Navigation/CLOSE_DRAWER',
  TOGGLE_DRAWER: 'Navigation/TOGGLE_DRAWER',
  DRAWER_OPENED: 'Navigation/DRAWER_OPENED',
  DRAWER_CLOSED: 'Navigation/DRAWER_CLOSED'
}

react-navigation.js line 825

但是,由于您未手动切换,所以说滑行所隐含的抽屉导航似乎不会触发OPEN_ / CLOSE_操作。不过,_OPENED / _CLOSED操作确实会在之后触发。

const MyDrawerNavigator = createDrawerNavigator(...);
const defaultGetStateForAction = MyDrawerNavigator.router.getStateForAction;

MyDrawerNavigator.router.getStateForAction = (action, state) => {
  switch (action.type) {
    case 'Navigation/OPEN_DRAWER':
    case 'Navigation/DRAWER_OPENED':
      StatusBar.setHidden(true, 'slide');
      break;
      
    case 'Navigation/CLOSE_DRAWER':
    case 'Navigation/DRAWER_CLOSED':
      StatusBar.setHidden(false, 'slide');
      break;
    }

  return defaultGetStateForAction(action, state);
};

答案 3 :(得分:2)

使用“反应导航”:“ ^ 3.5.1”

const defaultGetStateForAction = DrawerNav.router.getStateForAction;

DrawerNav.router.getStateForAction = (action, state) => {

    if(action){
        if(action.type == 'Navigation/MARK_DRAWER_SETTLING' && action.willShow){   
            StatusBar.setHidden(true);
        } else if(action.type == 'Navigation/MARK_DRAWER_SETTLING' && !action.willShow) {
            StatusBar.setHidden(false);
        }
    }

    return defaultGetStateForAction(action, state);
};

答案 4 :(得分:1)

我发现与asdfghjklm类似。

这是我的代码,即使您使用滑动打开-然后使用按钮将其关闭,该代码也可以正常运行

openCloseDrawer = (props) => {
  if (props.navigation.state.index == 1) {
    props.navigation.navigate('DrawerClose');
  } else {
    props.navigation.navigate('DrawerOpen');
  }
}

当用户点击“打开/关闭抽屉”按钮时,我将执行此功能。

答案 5 :(得分:1)

基于fredrivett(谢谢您)的解决方案Brad Bumbalough,我找到了一种响应速度更快的解决方案(其他解决方案在某些用途上延迟了secons)。

const defaultGetStateForAction = StackLogadoDrawer.router.getStateForAction;

StackLogadoDrawer.router.getStateForAction = (action, state) => {
  switch (action.type) {
    case 'Navigation/MARK_DRAWER_SETTLING':
      if (action.willShow == false) {
        console.log('CERRADO');
      } else if (action.willShow == true) {
        console.log('ABIERTO');
      }
      break;
    }

  return defaultGetStateForAction(action, state);
};

这是在操作立即(或非常接近)发生时触发的。

它适用于手势或调用openDrawer()

无论如何,我认为这是API中“必须具备”的简单直接的方法

答案 6 :(得分:1)

现在在反应导航5中,您可以使用此方法直接访问抽屉的状态:

useIsDrawerOpen() 是用于检测抽屉是否在父导航器中打开的挂钩。

例如,您可以使用以下方法来测试抽屉是否打开:

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

const MainContainer = () => {
   return (
    <View style={(useIsDrawerOpen()) ? styles.conatinerOpenStyle : styles.containerClosedStyle}>
        <Text>{console.log("Test drawer  "+useIsDrawerOpen())}</Text>

    </View>
);}

答案 7 :(得分:0)

嗯,并没有真正看到太多。一种方法是使用以下方法手动控制抽屉的打开/关闭:

this.props.navigation.navigate('DrawerOpen'); // open drawer
this.props.navigation.navigate('DrawerClose'); // close drawer

通过这种方式,您可以将关闭/打开事件包装在一个函数中,您可以在打开/关闭之前执行任何操作。

我在他们的文档中看到的唯一其他可能的解决方案是使用自定义contentComponent。你可以将一个函数传递给onItemPress(route)事件,所以也许你可以尝试挂钩。

答案 8 :(得分:0)

这在React-Native中工作正常,不确定React

对于我来说,我不得不更改 StatusBar ,因此我不需要知道抽屉是否完全关闭,因此下面的代码对我有用...

props.navigation.state.drawerMovementDirection === 'closing'
        ? //it is closing not fully closed
        : (props.navigation.state.drawerMovementDirection === 'opening' ||
            props.navigation.state.isDrawerOpen) && (
          //fully opened or opening 
        )

如果您不需要立即了解信息,则可以使用下面的代码,它可以正常工作,并且无论抽屉是打开还是不打开,都将为您提供准确的答案!

注意:这将延迟回答,对于我来说,这需要1秒钟。

        props.navigation.state.isDrawerOpen?
                //open
                :
                //close;

如果解决方案不起作用,我非常抱歉,但最重要的是,答案没有起作用!这是适合我的版本:))

答案 9 :(得分:0)

对于希望将其连接起来以使抽屉事件在您的屏幕或组件之一而不是顶级应用程序中可用的任何人来说,我都可以使用this post中所述的screenProps将其连接起来。您首先在应用程序上设置screenProps,然后将路由器以及您需要的其他任何东西传递出去。您可以将screenProps摘下道具,然后将其用于屏幕或组件(在此示例中,我将其连接到构造函数中),使用getStateForAction设置组件中的setState来关闭路由器事件。

这里是一个示例(为清晰起见,删除了一些代码)

App.js

import React from 'react';
import { AppLoading } from 'expo';

import {
  createDrawerNavigator,
  createAppContainer,
  createStackNavigator,
} from 'react-navigation';

import { HomeScreen } from './src/screens/HomeScreen.android';
import { LanguageSelectScreen } from './src/screens/LanguageSelectScreen';

export default class App extends React.Component {
  state = {
    isLoadingComplete: false,
    isTilted: false,
  };

  constructor() {
    super();
  }

  render() {
    if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
      return (
        <AppLoading  />
      );
    } else {
      return (
        <MyApp screenProps={MyAppNavigator.router} />
      );
    }
  }
}

const MyAppNavigator = createDrawerNavigator(
  {
    Home: {
      screen: HomeScreen,
    },
    PlayerNameScreen: {
      screen: PlayerNameScreen,
    },
  },
  {
    unmountInactiveRoutes: true,
    initialRouteName: 'PlayerNameScreen',
  },
);

const RootStack = createStackNavigator(
  {
    Main: {
      screen: MyAppNavigator,
    },
    MyModal: {
      screen: LanguageSelectScreen,
    },
  },
  {
    mode: 'modal',
    headerMode: 'none',
  },
);

export const MyApp = createAppContainer(RootStack);

HomeScreen.android.js

import React from 'react';
import {Icon} from 'react-native-elements';

export class HomeScreen extends React.Component {
  static navigationOptions = {
    drawerLabel: () => 'Home',
    drawerIcon: ({ tintColor }) => (
      <Icon
        name="checkerboard"
        type="material-community"
        size={25}
        color={tintColor}
      />
    ),
  };

  constructor(props) {
    super(props);

    const router = props.screenProps;

    const defaultGetStateForAction = router.getStateForAction;

    router.getStateForAction = (action, state) => {
      switch (action.type) {
        case 'Navigation/MARK_DRAWER_SETTLING':
          if (action.willShow == false) {
            console.log('CLOSED');
            this.setState({ isTilted: false });
          } else if (action.willShow == true) {
            this.setState({ isTilted: true });
            console.log('OPEN');
          }
          break;
      }

      return defaultGetStateForAction(action, state);
    };

    this.state = {
      isTilted: false,
    };
  }

  render() {
    const { isTilted } = this.state;

    // ... render using isTilted
  }

}

答案 10 :(得分:-1)

如果没有Redux集成,可以在路由器组件上使用 onNavigationStateChange 。只需截取抽屉动作: DrawerOpen DrawerClose

示例:

  handleNavigationState = (previous, next, action) => {    
    if (action.routeName === 'DrawerOpen') {
      this.props.setDrawerState(true);
    } else if (action.routeName === 'DrawerClose') {
      this.props.setDrawerState(false);
    }
  }

  render() {
    return (
      <Router onNavigationStateChange={this.handleNavigationState} />
    );
  }

答案 11 :(得分:-1)

我知道这已经很晚了,但对于那些正在寻找答案的人来说:

抽屉打开/关闭的逻辑是:

this.props.navigation.state.routes[0].index

关闭为0,开放为1。

您还可以使用

切换抽屉

this.props.navigation.navigate('DrawerToggle')

而不是

this.props.navigation.navigate('DrawerOpen');

this.props.navigation.navigate('DrawerClose');

对我来说似乎更方便,我还没有遇到任何问题。虽然很高兴知道它们是否被切换以便调用其他动作。

我真的相信React-Navigation是我见过的最糟糕的文档之一。有些命令没人知道。我在文档中找不到DrawerToggle操作,我只是通过使用console.log(this.props.navigation)来发现它;