【问题标题】:Get the current active screen route of the tab navigator in react navigationreact导航中获取标签导航器当前活动屏幕路径
【发布时间】:2019-08-07 12:00:47
【问题描述】:

这是我使用反应导航的导航堆栈v3.2.1

  1. 我有一个切换导航器来切换到身份验证导航堆栈和经过身份验证的应用堆栈。

  2. App 堆栈是使用底部选项卡导航器制作的。

  3. 我想为选项卡导航器使用自定义组件。

在使用createBottomTabNavigator 和自定义tabBarComponent 时如何获取选项卡导航器的当前路由名称。

例如:

  1. 假设标签导航堆栈有 2 个导航屏幕,即主页和聊天。
  2. 在自定义BottomBar中,如何查看focus/active/current routeName是否为Home/Chat,以便分别更改图标样式?

AppContainer.js

const switchStack = createSwitchNavigator({
    AuthLoading: AuthLoadingScreen,
    App: AppStack,
    Auth: AuthStack
}, {
    initialRouteName: 'AuthLoading',
})

export default createAppContainer(switchStack)

AppStack.js

const AppStack = createBottomTabNavigator({
    Home: {
        screen: HomeStack,
    },
    Chat: {
        screen: ChatStack
    },
}, {
    initialRouteName: 'Home',
    activeColor: '#f0edf6',
    inactiveColor: '#3e2465',
    shifting: false,
    barStyle: {
        backgroundColor: '#694fad',
    },
    labeled: false,
    tabBarComponent: ({navigation}) => <BottomBar navigation={navigation}/>
})

export default AppStack

BottomBar.js

export default class BottomBar extends React.Component {
    constructor(props) {
        super(props)
    }

    render() {
        return (
            <View style={styles.container}>
                <IconComponent routeName={'Home'}/>
                <IconComponent routeName={'Chat'}/>
            </View>
        )
    }
}

图标组件.js

export default class IconComponent extends React.Component {
    constructor(props) {
        super(props)
    }

    ...

    render() {
        let IconComponent
        let iconName
        let iconSize = 25
        switch (this.props.routeName) {
            case 'Home':
                IconComponent = MaterialCommunityIcons
                // iconName = `home${focused ? '' : '-outline'}`;
                iconName = `home`;
                break
            case 'Chat':
                IconComponent = AntDesign
                iconName = `message1`
                iconSize = 22
                break
        }

        let tintColor = 'green'

        // if focused Home is current tab screen then change style eg. tint color.
        // similary if current tab screen is Chat, then change style.

        return (
                <Animated.View
                    style={[
                        styles.container,
                        {
                            opacity: this.opacity
                        }
                    ]}
                >
                    <IconComponent name={iconName} size={iconSize} color={tintColor}/>
                </Animated.View>
        )
    }
}

【问题讨论】:

    标签: reactjs react-native react-navigation


    【解决方案1】:

    自定义 BottomBar 的导航对象有一个索引来保存当前活动屏幕索引

    tabBarComponent: ({navigation}) => <BottomBar navigation={navigation}/>
    
    navigation.state.index
    

    如果主屏幕处于活动状态 >> navigation.state.index 将为 0 如果聊天屏幕处于活动状态 >> navigation.state.index 将为 1 ...等

    【讨论】:

    • 我想这实际上可能适用于我的用例。我会进一步调查并很快回来。
    • 这实际上是正确的解决方案,我已经尝试过了,它工作正常,适合我的用例
    【解决方案2】:

    您可以使用tabBarIcon 属性来设置图标,而不是为图标设置一个全新的tabBarComponent。你可以在Tab Navigation Docs找到一个例子

    • tabBarIconnavigationOptions 上的一个属性,所以我们知道我们可以在屏幕组件上使用它,但是在这种情况下选择放置它 在createBottomTabNavigator 配置中以集中 方便起见的图标配置。
    • tabBarIcon 是一个函数,它给出了 focused statetintColorhorizontal 参数,它是一个布尔值。如果你采取 在配置中再往下看,你会看到tabBarOptionsactiveTintColorinactiveTintColor。这些默认为 iOS 平台默认设置,但您可以在此处更改它们。这 传递给tabBarIcontintColor 是 活动或非活动一个,取决于focused 状态(重点是 积极的)。方向状态horizontal 在设备处于 横向,否则为 false 纵向。
    • 阅读full API reference,了解有关createBottomTabNavigator 配置选项的更多信息。

    示例 (来自文档)

    export default createBottomTabNavigator(
      {
        Home: HomeScreen,
        Settings: SettingsScreen,
      },
      {
        defaultNavigationOptions: ({ navigation }) => ({
          tabBarIcon: ({ focused, horizontal, tintColor }) => {
            const { routeName } = navigation.state;
            let IconComponent = Ionicons;
            let iconName;
            if (routeName === 'Home') {
              iconName = `ios-information-circle${focused ? '' : '-outline'}`;
              // Sometimes we want to add badges to some icons. 
              // You can check the implementation below.
              IconComponent = HomeIconWithBadge; 
            } else if (routeName === 'Settings') {
              iconName = `ios-options${focused ? '' : '-outline'}`;
            }
    
            // You can return any component that you like here!
            return <IconComponent name={iconName} size={25} color={tintColor} />;
          },
        }),
        tabBarOptions: {
          activeTintColor: 'tomato',
          inactiveTintColor: 'gray',
        },
      }
    );
    

    【讨论】:

    • 是的,这实际上是我以前的工作方式。但由于我需要向标签栏添加一些额外的功能(例如浮动操作按钮),所以我使用的是自定义组件。
    【解决方案3】:

    在 React Navigation 5.x 中使用功能组件。您可以使用 useIsFocused 钩子。

    import { useIsFocused } from "@react-navigation/native"; 
    

    用法:在您要检测的每个选项卡屏幕中,它们是当前处于活动状态还是处于焦点状态。

    const isFocused = useIsFocused();
    
    if (isFocused) {
      // the screen is currently focused
      // your code here
    }
    

    文档:https://reactnavigation.org/docs/function-after-focusing-screen/

    【讨论】:

      【解决方案4】:

      您可以使用navigation.state.routeName

      tabBarComponent: ({navigation}) => <BottomBar navigation={navigation} currentRouteName={navigation.state.routeName} />
      

      或者更好的是你可以这样做:

      const TabNavigator = createBottomTabNavigator({
          Home: Home,
          Chat: Chat
      },
      {
          defaultNavigationOptions: ({ navigation }) => ({
              tabBarIcon: ({ focused, horizontal, tintColor }) => {
                  if (navigation.state.routeName === 'Home') {
                      return <Icon name='ios-home' size={30} color={tintColor} />
                  } else if (navigation.state.routeName === 'Chat') {
                      return <Icon name='ios-heart' size={30} color={tintColor} />
                  }
              },
              tabBarOptions: {
                  activeTintColor: '#2BEDBA',
                  inactiveTintColor: '#FAFAFA',
                  style: { backgroundColor: '#000', paddingTop: 5 }
              },
          })
      });
      

      【讨论】:

      • 我之前其实也试过这种方式,但是这个方法不是Home或者Chat,而是只返回App栈路由名,它来自顶层switch navigator栈。跨度>
      • 道具routenavigation.state移出,现在是:({navigation, route}) =&gt; &lt;BottomBar navigation={navigation} currentRouteName={route.name} /&gt;
      【解决方案5】:

      正如@Biskrem Muhammad 建议的那样,这是可行的:

      export function SignUp(props: TSignupProps) {
        const { navigation, route } = props;
        console.log('Im in screen:', route.name)
        .
        .
        .
      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多