如何确定 DrawerNavigator 中的活动路线以着色活动菜单项并关闭抽屉
How to determine active route in DrawerNavigator to tint the active menu Item and close the drawer
我正在使用 React Navigation 库。我已经编写了一个自定义抽屉菜单并将其添加到我的导航器的 contentComponent 配置中。我不知道如何从自定义菜单中确定哪个 page/screen 处于活动状态。这是我的 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>
)
};
如果我选择不同的页面,我可以很好地导航(如果我在 "Search Location" 页面上并且我想转到 "Sign In" 页面,一切都按预期工作)。但是,如果我在 "Search Locations" 页面上单击 "Search Locations" 菜单项,我只想关闭抽屉。我还想为活动页面 icon/label 着色。我的问题是,在 DrawerMenu.js 文件中,我不知道如何确定我当前所在的页面来执行此操作。
我是否正确执行了此操作?我是 React Native 的新手。提前致谢。
我找到了一种方法,但我想知道是否有 better/simpler 方法比我想出的方法更好。我添加了一些挂钩(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;
对于反应导航 v5,您可以使用:
const DrawerMenu = (props) =>
const { state } = props
const { routes, index } = state;
const focusedRoute = routes[index].name; // this is the active route
.....
我正在使用 React Navigation 库。我已经编写了一个自定义抽屉菜单并将其添加到我的导航器的 contentComponent 配置中。我不知道如何从自定义菜单中确定哪个 page/screen 处于活动状态。这是我的 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>
)
};
如果我选择不同的页面,我可以很好地导航(如果我在 "Search Location" 页面上并且我想转到 "Sign In" 页面,一切都按预期工作)。但是,如果我在 "Search Locations" 页面上单击 "Search Locations" 菜单项,我只想关闭抽屉。我还想为活动页面 icon/label 着色。我的问题是,在 DrawerMenu.js 文件中,我不知道如何确定我当前所在的页面来执行此操作。
我是否正确执行了此操作?我是 React Native 的新手。提前致谢。
我找到了一种方法,但我想知道是否有 better/simpler 方法比我想出的方法更好。我添加了一些挂钩(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;
对于反应导航 v5,您可以使用:
const DrawerMenu = (props) =>
const { state } = props
const { routes, index } = state;
const focusedRoute = routes[index].name; // this is the active route
.....