Need to show Expandable list view inside navigation drawer

拥有回忆 提交于 2021-01-25 07:22:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!