skip to Main Content

how get selected index of multiple ExpansionTile in flutter ?
i need sidebar menu with multiple expansiontile and listtile.
how can i get selected index to change selected color menu with provider or bloc ?

enter image description here

   children: [
              ExpansionTile(
                title: Text('main a'),
                children: [
                  ListTile(
                    title: Text('a1'),
                  ),
                  ListTile(
                    title: Text('a2'),
                  ),
                  ExpansionTile(
                    title: Text('a3'),
                    children: [
                      ListTile(
                        title: Text('a31'),
                      ),
                      ListTile(
                        title: Text('a32'),
                      ),
                      ListTile(
                        title: Text('a32'),
                      ),
                    ],
                  ),
                ],
              ),
              ExpansionTile(
                title: Text('main b'),
                children: [
                  ListTile(
                    title: Text('b1'),
                  ),
                  ListTile(
                    title: Text('b2'),
                  ),
                  ListTile(
                    title: Text('b3'),
                  ),
                ],
              ),
            ],

3

Answers


  1. You can use onTap from ListTile, and create state variables to hold selected item. Like here I am using String. Based on your data, creating model class or map might be better choice.

      String? aValue;
    
      ....
    
      ExpansionTile(
                title: Text('main a'),
                children: [
                  ListTile(
                    title: Text('a1'),
                    onTap: () {
                      aValue = "a1";
                      setState(() {});
                    },
                  ),     
    
    Login or Signup to reply.
  2. This is a hassle to dynamically change the color of the ListTile() which have two different parent widget but with some extra code, you can do the same.


    Full Code

    // You can also use `Map` but for the sake of simplicity I'm using two separate `List`.
      final List<String> _parentlist1 = ["a1", "a2"];
      final List<String> _childOfParentlist1 = ["a31", "a32", "a34"];
      final List<bool> _isSelectedForParentList1 = List.generate(
          2,
          (i) =>
              false); // Fill it with false initially and this list for all the textList
      final List<bool> _isSelectedForChildOfParentList1 =
          List.generate(2, (i) => false);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: ExpansionTile(
            title: const Text('main a'),
            children: [
              ListView.builder(
                itemBuilder: (_, i) {
                  return ListTile(
                    tileColor: _isSelectedForParentList1[i]
                        ? Colors.blue
                        : null, // If current item is selected show blue color
                    title: Text(_parentlist1[i]),
                    onTap: () => setState(() => _isSelectedForParentList1[i] =
                        !_isSelectedForParentList1[i]), // Reverse bool value
                  );
                },
              ),
              ExpansionTile(
                title: const Text('a3'),
                children: [
                  ListView.builder(
                    itemBuilder: (_, i) {
                      return ListTile(
                        tileColor: _isSelectedForChildOfParentList1[i]
                            ? Colors.blue
                            : null, // If current item is selected show blue color
                        title: Text(_childOfParentlist1[i]),
                        onTap: () => setState(() =>
                            _isSelectedForChildOfParentList1[i] =
                                !_isSelectedForChildOfParentList1[
                                    i]), // Reverse bool value
                      );
                    },
                  ),
                ],
              ),
            ],
          ),
        );
      }
    
    Login or Signup to reply.
  3. You can use a ListView to contain the ExpansionTile widgets and a ListTile widgets. Then you can use a currentIndex variable to keep track of the index of the currently selected menu item. You can use a Provider or BLoC to manage the currentIndex variable and to notify the widget tree when the value of currentIndex changes.

    Here is the full code

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    
    void main() {
      runApp(
        ChangeNotifierProvider(
          create: (context) => MenuModel(),
          child: MyApp(),
        ),
      );
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: HomePage(),
        );
      }
    }
    
    class HomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('ExpansionTile Demo'),
          ),
          body: MenuList(),
        );
      }
    }
    
    class MenuList extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        final model = Provider.of<MenuModel>(context);
        return ListView(
          children: <Widget>[
            ExpansionTile(
              title: Text('Menu 1'),
              children: <Widget>[
                ListTile(
                  title: Text('Menu 1.1'),
                  onTap: () {
                    model.updateIndex(0);
                  },
                  selected: model.currentIndex == 0,
                ),
                ListTile(
                  title: Text('Menu 1.2'),
                  onTap: () {
                    model.updateIndex(1);
                  },
                  selected: model.currentIndex == 1,
                ),
              ],
            ),
            ExpansionTile(
              title: Text('Menu 2'),
              children: <Widget>[
                ListTile(
                  title: Text('Menu 2.1'),
                  onTap: () {
                    model.updateIndex(2);
                  },
                  selected: model.currentIndex == 2,
                ),
                ListTile(
                  title: Text('Menu 2.2'),
                  onTap: () {
                    model.updateIndex(3);
                  },
                  selected: model.currentIndex == 3,
                ),
              ],
            ),
          ],
        );
      }
    }
    
    class MenuModel with ChangeNotifier {
      int _currentIndex = 0;
    
      int get currentIndex => _currentIndex;
    
      void updateIndex(int index) {
        _currentIndex = index;
        notifyListeners();
      }
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search