skip to Main Content

I successfully achieve the sidebar menu by using drawer and ListTile, but the problem is when the ListTile tapped and the drawer closed, I reopen the drawer will see that the tapped ListTile will be reset to untapped color. How to solve this problem? I try so many time but I can’t figure the solution out.

menu_list dart file

class MenuList extends StatefulWidget {
  final Function(int, String) onTap;

  List<Map<String, dynamic>> menu = [];
  MenuList({required this.onTap, required this.menu});

  @override
  State<MenuList> createState() => _MenuListState();
}

class _MenuListState extends State<MenuList> {
  int _selectedIndex = 0;

  Widget buildListTile(Map<String, dynamic> item, int index) {
    return ListTile(
      title: Text(
        item["title"],
        style: TextStyle(
            color: _selectedIndex == index ? Colors.deepOrangeAccent : Colors.grey,
        ),
      ),
      leading: Icon(
        item['leading'],
        color: _selectedIndex == index ? Colors.deepOrangeAccent : Colors.grey,
      ),
      tileColor: Colors.white,
      onTap: (){
        setState(() {
          _selectedIndex = index;
        });
        widget.onTap(index, item['title']);
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: widget.menu.length,
        itemBuilder: (BuildContext context, int index) {
          return buildListTile(widget.menu[index], index);
        },
      ),
    );
  }
}

mDashboard dart file

class MobileDashboard extends StatefulWidget {

  @override
  State<MobileDashboard> createState() => _MobileDashboardState();
}

class _MobileDashboardState extends State<MobileDashboard> {

  final _auth = FirebaseAuth.instance;
  final PageController _pageController = PageController(initialPage: 0);
  String _selectedTitle = '';
  final List<Map<String, dynamic>> menu = [
    {'title': 'Playlists', 'leading':Icons.featured_play_list},
    {'title': 'Menu..', 'leading':Icons.send},
    {'title': 'Logout', 'leading':Icons.logout},
  ];

  void handleTap(int index, String title) {
    setState(() {
      _selectedTitle = title;
    });
  }

  @override
  void initState() {
    _selectedTitle = 'Playlists';
    super.initState();
  }

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      endDrawer: Drawer(
          child: ListView(
              children: [
                SizedBox(
                  height: 100,
                  child: DrawerHeader(
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.end,
                      children: [
                        Expanded(
                          child: Align(
                            alignment: Alignment.centerLeft,
                            child: IconButton(
                                onPressed: (){
                                  Get.back(result: false);
                                },
                                icon: Icon(CupertinoIcons.xmark)
                            ),
                          ),
                        ),
                        Icon(Icons.info_outline, size: 24, color: Colors.grey,),
                        SizedBox(width: 27.3,),
                        SizedBox(
                          width: 28,
                          height: 28,
                          child: CircleAvatar(backgroundImage: AssetImage('assets/loginBG.png'),),
                        ),

                      ],
                    ),
                  ),
                ),
                SizedBox(
                  width: MediaQuery.of(context).size.width,
                  height: MediaQuery.of(context).size.height,
                  child: MenuList(
                      onTap: handleTap,
                      menu: menu),
                )
              ]
          )
      ),

2

Answers


  1. You can pass the initial index on MenuList.

    class MenuList extends StatefulWidget {
      const MenuList({
        this.initialSelectedIndex = 0,
        required this.onTap,
        required this.menu,
      });
      final Function(int, String) onTap;
      final List<Map<String, dynamic>> menu;
      final int initialSelectedIndex;
    
      @override
      State<MenuList> createState() => _MenuListState();
    }
    
    class _MenuListState extends State<MenuList> {
      late int _selectedIndex = widget.initialSelectedIndex;
    
      Widget buildListTile(Map<String, dynamic> item, int index) {
        return ListTile(
          title: Text(
            item["title"],
            style: TextStyle(
              color:
                  _selectedIndex == index ? Colors.deepOrangeAccent : Colors.grey,
            ),
          ),
          leading: Icon(
            item['leading'],
            color: _selectedIndex == index ? Colors.deepOrangeAccent : Colors.grey,
          ),
          tileColor: Colors.white,
          onTap: () {
            setState(() {
              _selectedIndex = index;
            });
            widget.onTap(index, item['title']);
          },
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: ListView.builder(
            itemCount: widget.menu.length,
            itemBuilder: (BuildContext context, int index) {
              return buildListTile(widget.menu[index], index);
            },
          ),
        );
      }
    }
    

    And on usecase(on state class)

    
      int selectedIndex = 0;
    
      void handleTap(int index, String title) {
        selectedIndex = index;
        setState(() {
          _selectedTitle = title;
        });
        .....code...
      }
      
    

    inside build method

     MenuList(
      onTap: handleTap,
      menu: menu,
      initialSelectedIndex: selectedIndex,
    ),
    
    Login or Signup to reply.
  2. See the problem is, when you click on other item in your menu , it goes to other page lets say menu, Now again again page gets build and then MenuList() is called, inside MenuList() you have written int selectedindex = 0, so always it will display playlist. approach is also not a good one

    Better approach is

    1. Make a List of pages/Widgets you want to show like

      static final List_widgetOptions = [
      const Text("Home"),
      UserProfilePage(),
      const Text("Search"),
      const Text("Settings")
      ];

        void _onItemTapped(int index){
          setState(() {
            _selectedIndex = index;
          });
        }
      
    2. then write drawer code when user taps on item it would get routed to widget we define in above list

      @override
      Widget build(BuildContext context) {
      return Drawer(
      child: ListView(
      children: [

              UserAccountsDrawerHeader(
      
                accountName: GestureDetector(
                // onTap: () => setState(() {
                //     _selectedIndex = 1;
                //   }),
                onTap: () {
                  setState(() {
                    _selectedIndex = 1;
                  });
                  Navigator.pop(context);
                },
                child:const Text("username",style: TextStyle(fontSize: 20) ,)), 
              currentAccountPicture: CircleAvatar(
                child:  ClipOval(
                  child: Image.asset('lib/images/dhruv.png.jpg',
                  width:90,
                  height : 90,
                  fit :BoxFit.cover),
      
      
      
                  )
      
              ),
      
              accountEmail:const Text("email")),
              ListTile(
                leading: Icon(Icons.payment),
                title: const Text("Home"),
                 onTap: () {
                   Navigator.pop(context);
                  setState(() {
                    _selectedIndex = 0;
                  });
                  Navigator.pop(context);
      
                },
              ),
      

    code is different but understand the flow, we need to call pages from the drawer itself, and not like, from a page call a drawer

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search