问题
I am an Android Application Developer. I have started working on React-Native. I am unable to find a way to show expandable list inside navigation drawer. Suggest a library if this functionality can be done in that.navigationOptions
does not have a way to provide a list (refer code below).
I want to show expandable view like item 4
My Code is :-
import {DrawerNavigator} from 'react-navigation';
import React, {Component} from 'react';
import {
Platform,
StyleSheet,
Text,
Image,
View,
TouchableHighlight
} from 'react-native';
import Screen1 from './screen/Screen1'
import Screen2 from './screen/Screen2'
const util = require('util');
class MyHomeScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
headertitle: 'ffffff'
};
}
componentWillReceiveProps(nextProps) {
navigationOptions = {
title: this.nextProps.headertitle
};
}
static navigationOptions = {
drawerLabel: 'Home',
drawerIcon: ({tintColor}) => (
<Image
source={require('./images/document.png')}
style={[
styles.icon, {
tintColor: tintColor
}
]}/>),
title: 'NIIT'
};
render() {
return (<Screen1/>);
}
}
class MyNotificationsScreen extends React.Component {
static navigationOptions = {
drawerLabel: 'Notifications',
drawerIcon: ({tintColor}) => (<Image source={require('./images/smartphone.png')} style={[styles.icon]}/>),
title: 'Gnome'
};
render() {
return (<Screen2/>);
}
}
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24
}
});
const DrawerScreen = DrawerNavigator({
Screen1: {
screen: MyHomeScreen
},
Screen2: {
screen: MyNotificationsScreen
}
}, {headerMode: 'none'})
export default DrawerScreen;
回答1:
react-navigation does not, at this time, support a collapsible menu in the drawer navigator.
You can, however, implement your own, by supplying your own contentComponent
to the navigator:
const DrawerScreen = DrawerNavigator({
Screen1: {
screen: MyHomeScreen
},
Screen2: {
screen: MyNotificationsScreen
}
}, {
headerMode: 'none',
contentComponent: MyDrawer
})
const MyDrawer = (props) => ...
See the documentation for more information.
You can use something like react-native-collapsible to achieve the effect of the collapsible menu itself.
回答2:
I think this is a single class, simple implementation of what the OP is asking for. It uses react-navigation v5. It's a standalone component that is configured via the ExpandableDrawerProps
(title
is the name of parent drawer, i.e. what contains the subdrawers and has no navigation, and choices is a map of label name to navigation screen component names.) It is written in TypeScript (both of these are .tsx files), so if you're not using TypeScript, just strip out the typing.
import {
DrawerContentComponentProps,
DrawerContentScrollView,
DrawerItem,
} from '@react-navigation/drawer';
import React from 'react';
import { Text, View } from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import styles from './styles';
export type ExpandableDrawerProps = DrawerContentComponentProps & {
title: string;
choices: Map<string, string>;
};
export default class ExpandableDrawer extends React.Component<
ExpandableDrawerProps,
{
isExpanded: boolean;
}
> {
constructor(props: ExpandableDrawerProps, state: { isExpanded: boolean }) {
super(props);
this.state = state;
}
onPress = (): void => {
this.setState(() => {
return {
isExpanded: !this.state.isExpanded,
};
});
};
render = (): JSX.Element => {
return (
<View style={styles.container}>
<TouchableOpacity
activeOpacity={0.8}
onPress={this.onPress}
style={styles.heading}
>
<Text style={styles.expander}>{this.props.title}</Text>
</TouchableOpacity>
{this.state.isExpanded ? (
<DrawerContentScrollView>
<View style={styles.expandedItem}>
{[...this.props.choices.keys()].map(
(label: string): JSX.Element | null => {
const screen = this.props.choices.get(label);
if (screen != undefined) {
return (
<DrawerItem
key={label}
label={label}
onPress={(): void => {
this.props.navigation.navigate(screen);
}}
/>
);
} else {
return null;
}
}
)}
</View>
</DrawerContentScrollView>
) : null}
</View>
);
};
}
You can drop that code in a file, make a simple styles file or remove them from that code, and then you're able to use <ExpandableDrawerMenu {...expandable} />
in your normal drawer navigation.
Here's how I used it in a normal navigation drawer.
const DrawerContent = (props: DrawerContentComponentProps): JSX.Element => {
const c = new Map<string, string>();
c.set('SubItem 1', 'SubItem1');
c.set('SubItem 2', 'SubItem2');
const expandable: ExpandableDrawerProps = {
title: 'Expandable Drawer',
choices: c,
navigation: props.navigation,
state: props.state,
descriptors: props.descriptors,
progress: props.progress,
};
return (
<DrawerContentScrollView {...props}>
<View style={styles.drawerContent}>
<Drawer.Section style={styles.drawerSection}>
<DrawerItem
label="Item 1"
onPress={(): void => {
props.navigation.navigate('Item1');
}}
/>
<ExpandableDrawerMenu {...expandable} />
<DrawerItem>
label="Item 2"
onPress={(): void => {
props.navigation.navigate('Item2');
}}
/>
<DrawerItem
label="Item 3"
onPress={(): void => {
props.navigation.navigate('Item3');
}}
/>
</Drawer.Section>
</View>
</DrawerContentScrollView>
);
};
export default class Navigator extends Component {
render = (): JSX.Element => {
const Drawer = createDrawerNavigator();
return (
<NavigationContainer>
<Drawer.Navigator
drawerContent={(props: DrawerContentComponentProps): JSX.Element =>
DrawerContent(props)
}
initialRouteName="Item1"
>
<Drawer.Screen name="Item1" component={Item1Screen} />
<Drawer.Screen name="SubItem1" component={SubItem1Screen} />
<Drawer.Screen name="SubItem2" component={SubItem2Screen} />
<Drawer.Screen name="Item2" component={Item2Screen} />
<Drawer.Screen name="Item3" component={Item3Screen} />
</Drawer.Navigator>
</NavigationContainer>
);
};
}
回答3:
I have developed a solution for this problem. My code uses
"@react-navigation/drawer": "^5.1.1" and
"@react-navigation/native": "^5.0.9".
Gihub link - https://github.com/gyanani-harish/ReactNative-ExpandableDrawerMenu
来源:https://stackoverflow.com/questions/47766564/need-to-show-expandable-list-view-inside-navigation-drawer