【问题标题】:How to determine active route in DrawerNavigator to tint the active menu Item and close the drawer如何在 DrawerNavigator 中确定活动路线以着色活动菜单项并关闭抽屉
【发布时间】:2019-10-03 15:17:18
【问题描述】:

我正在使用 React Navigation 库。我编写了一个自定义抽屉菜单并将其添加到我的导航器的 contentComponent 配置中。我不知道如何从自定义菜单中确定哪个页面/屏幕处于活动状态。这是我的 DrawerNavigator 代码:

const DrawerNavigator = createDrawerNavigator({
    "Search Locations": {
        screen: SearchLocationsScreen,
    },
    "About": {
        screen: AboutScreen
    },
    "Favorites": {
        screen: FavoritesScreen
    },
    "Sign In": {
        screen: SignIn
    },
}, {
    contentComponent: props => <CustomDrawerComponent {...props} />
});

请注意,我的 DrawerNavigator 嵌套在 StackNavigator 中。我将导航选项导出到一个单独的文件,如下所示:

export default (navigation) => {
    const {state} = navigation;
    let navOptions = {};

    if(state.index === 0){
        navOptions.headerRight = (
            <TouchableOpacity>
                <MaterialIcons
                    name="my-location"
                    size={32}
                    color="#fff"
                    style={{paddingRight: 10}} />
            </TouchableOpacity>
        )
    }

        if (state.isDrawerOpen){
        navOptions.headerLeft = (
            <>
                <StatusBar barStyle='light-content'/>
                <TouchableOpacity onPress={() => {
                    navigation.dispatch(DrawerActions.toggleDrawer())
                }}>
                    <Ionicons name="ios-close" style={styles.menuClose} size={38} color={'#fff'}/>
                </TouchableOpacity>
            </>
        )
    } else {
        navOptions.headerLeft = (
            <>
                <StatusBar barStyle='light-content'/>
                <TouchableOpacity onPress={() => {
                    navigation.dispatch(DrawerActions.toggleDrawer())
                }}>
                    <Ionicons name="ios-menu" style={styles.menuOpen} size={32} color={'#fff'}/>
                </TouchableOpacity>
            </>
        )
    }

    return navOptions;
};

我这样分配这些选项:

const MainStackNavigator = createStackNavigator({
    DrawerNavigator: {
        screen: DrawerNavigator,
        navigationOptions: ({navigation}) => configureDrawerOptions(navigation)
    }
}, {
    defaultNavigationOptions: configureDefaultStackNavOptions
});

我的自定义 DrawerMenu 如下所示:

const DrawerMenu = (props) => {

    // let routes = props.navigation.state.routes;

    const navigateToScreen = (route) => () => {

        const navAction = NavigationActions.navigate({
            routeName: route
        });
        props.navigation.dispatch(navAction);
    };

    return (
        <ScrollView style={styles.root}>

            <View style={styles.rowContainer}>
                <TouchableOpacity onPress={navigateToScreen('Search Locations')}>
                    <View style={styles.row}>
                        <MaterialIcons name='location-searching' style={styles.icon} size={30}/>
                        <Text style={styles.label}>Search Locations</Text>
                    </View>
                </TouchableOpacity>
            </View>

            <View {...props} style={styles.rowContainer}>
                <TouchableOpacity onPress={navigateToScreen('About')}>
                    <View style={styles.row}>
                        <MaterialIcons name='info-outline' style={styles.icon} size={30}/>
                        <Text style={styles.label}>About</Text>
                    </View>
                </TouchableOpacity>
            </View>

            <View {...props} style={styles.rowContainer}>
                <TouchableOpacity onPress={navigateToScreen('Favorites')}>
                    <View style={styles.row}>
                        <MaterialIcons name='favorite-border' style={styles.icon} size={30}/>
                        <Text style={styles.label}>Favorites</Text>
                    </View>
                </TouchableOpacity>
            </View>

            <View {...props} style={styles.rowContainer}>
                <TouchableOpacity onPress={navigateToScreen('Sign In')}>
                    <View style={styles.row}>
                        <Ionicons name='md-log-in' style={styles.icon} size={30}/>
                        <Text style={styles.label}>Sign In</Text>
                    </View>
                </TouchableOpacity>
            </View>

        </ScrollView>
    )
};

如果我选择不同的页面,我可以很好地导航(如果我在“搜索位置”页面上并且我想转到“登录”页面,一切都会按预期工作)。但是,如果我在“搜索位置”页面上并单击“搜索位置”菜单项,我只想关闭抽屉。我还想为活动页面的图标/标签着色。我的问题是,从 DrawerMenu.js 文件中,我不知道如何确定我当前在哪个页面上执行此操作。

我是否正确实施了这一点?我是 React Native 的新手。提前致谢。

【问题讨论】:

  • 我认为你可以从 navigtion.state 道具中获取 activeroute
  • 我可以这样得到它:let activeIndex = props.navigation.state.index;让 activeRouteName = props.navigation.state.routes[activeIndex].routeName;不过应该有更好的方法......这有点冗长
  • 请查看此问题的答案stackoverflow.com/questions/59005239/…

标签: react-native react-navigation react-navigation-drawer


【解决方案1】:

对于反应导航 v5,您可以使用:

const DrawerMenu = (props) =>

const { state } = props
const { routes, index } = state; 
const focusedRoute = routes[index].name; // this is the active route

.....

【讨论】:

    【解决方案2】:

    我想出了一种方法,但我想知道是否有比我想出的更好/更简单的方法。我添加了一些钩子(useEffect、useState)并修改了我的 navigateToScreen 函数。这是我的代码。如果它对您有帮助,请点赞。如果您提供了比我更好的解决方案,我会将其作为公认的答案:

    const DrawerMenu = (props) => {
    
        let activeIndex = props.navigation.state.index;
        let activeRouteName = props.navigation.state.routes[activeIndex].routeName;
    
        const [activeRoute, setActiveRoute] = useState('');
    
        useEffect(() => {
            setActiveRoute(activeRouteName);
        }, [activeRouteName, activeRoute]);
    
    
        const navigateToScreen = (route) => () => {
    
            if (activeRouteName === route){
                return props.navigation.closeDrawer();
            }
    
            const navAction = NavigationActions.navigate({
                routeName: route
            });
    
            props.navigation.dispatch(navAction);
        };
    
        return (
            <ScrollView style={styles.root}>
    
                <View style={styles.rowContainer}>
                    <TouchableOpacity
                        onPress={navigateToScreen('Search Locations')}>
                        <View style={styles.row}>
                            <MaterialIcons
                                name='location-searching'
                                style={activeRouteName === "Search Locations" ? styles.activeIcon : styles.icon}
                                size={30}
                            />
                            <Text style={activeRouteName === "Search Locations" ? styles.activeLabel : styles.label}>
                                Search Locations
                            </Text>
                        </View>
                    </TouchableOpacity>
                </View>
    
                <View style={styles.rowContainer}>
                    <TouchableOpacity onPress={navigateToScreen('About')}>
                        <View style={styles.row}>
                            <MaterialIcons
                                name='info-outline'
                                style={activeRouteName === "About" ? styles.activeIcon : styles.icon}
                                size={30}
                            />
                            <Text style={activeRouteName === "About" ? styles.activeLabel : styles.label}>
                                About
                            </Text>
                        </View>
                    </TouchableOpacity>
                </View>
    
                <View style={styles.rowContainer}>
                    <TouchableOpacity onPress={navigateToScreen('Favorites')}>
                        <View style={styles.row}>
                            <MaterialIcons
                                name='favorite-border'
                                style={activeRouteName === "Favorites" ? styles.activeIcon : styles.icon}
                                size={30}
                            />
                            <Text style={activeRouteName === "Favorites" ? styles.activeLabel : styles.label}>
                                Favorites
                            </Text>
                        </View>
                    </TouchableOpacity>
                </View>
    
                <View style={styles.rowContainer}>
                    <TouchableOpacity onPress={navigateToScreen('Profile')}>
                        <View style={styles.row}>
                            <MaterialIcons
                                name='person-outline'
                                style={activeRouteName === "Profile" ? styles.activeIcon : styles.icon}
                                size={32}
                            />
                            <Text style={activeRouteName === "Profile" ? styles.activeLabel : styles.label}>
                                User Profile
                            </Text>
                        </View>
                    </TouchableOpacity>
                </View> 
            </ScrollView>
        )
    };
    
    const styles = StyleSheet.create({
        root: {
            marginTop: 20,
        },
        row: {
            flexDirection: 'row',
            paddingTop: 16,
            paddingBottom: 16,
            alignItems: 'center',
            justifyContent: 'flex-start'
        },
        icon: {
            marginRight: 25,
            color: '#fff',
            padding: 2,
        },
        activeIcon: {
            marginRight: 25,
            color: colors.accent,
            padding: 2,
        },
        label: {
            fontSize: 20,
            color: '#fff',
        },
        activeLabel: {
            fontSize: 20,
            color: colors.accent,
        },
        rowContainer: {
            marginHorizontal: 16,
        }
    
    });
    
    export default DrawerMenu;
    

    【讨论】:

      猜你喜欢
      • 2015-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多