Home > Enterprise >  How to Collapse already opened ExpansionPanel after clicking on another ExpansionPanel in Flutter?
How to Collapse already opened ExpansionPanel after clicking on another ExpansionPanel in Flutter?

Time:02-02

I read the questions that were asked in this regard, but I did not get an answer or I made a mistake somewhere According to the code I have, when clicking on each panel, the panels that were already open are not closed. And this is because I use one variable for all of them How can this be solved?


bool isExpanded = false;


ListView.builder(
                    itemBuilder: (context, index) {
                      return Column(
                        children: [
                          ExpansionPanelList(
                            expansionCallback: (panelIndex, isExpanded) {
                              setState(() {
                                isExpandeder = !isExpanded;
                              });
                            },
                            children: [
                              ExpansionPanel(
                                headerBuilder: (context, isExpanded) {
                                  return Row(
                                    children: [
                                      Text("Header"),
                                      const Spacer(),
                                      Text("username")
                                    ],
                                  );
                                },
                                body: Column(
                                  children: [
                                    Text(
                                      _signals![index].pair.toString(),
                                    ),
                                  ],
                                ),
                                isExpanded: isExpanded,
                              ),
                            ],
                          )
                        ],
                      );
                    },
                    itemCount: _signals!.length,
                  ),

CodePudding user response:

  1. You don't need to have a list of bool values to store expanded values since you have only one value maximum. You can store index of currently expanded tile.

  2. In your ListView you actually create multiple ExpansionPanelLists with one element each, instead of one list with all of them. You don't need a ListView at all.

You can try the following code in Dartpad, it does what you want.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  var content = ['text', 'more text', 'another text', 'random text'];
  int? expandedItemIndex;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SingleChildScrollView(
          child: ExpansionPanelList(
            expansionCallback: (panelIndex, isExpanded) {
              setState(() {
                if (!isExpanded) {
                  expandedItemIndex = panelIndex;
                } else {
                  expandedItemIndex = null;
                }
              });
            },
            children: [
              for (var i = 0; i < content.length; i  )
                ExpansionPanel(
                  headerBuilder: (context, isExpanded) {
                    return Text("Header $i");
                  },
                  body: Text(content[i]),
                  isExpanded: expandedItemIndex == i,
                ),
            ],
          ),
        ),
      ),
    );
  }
}

CodePudding user response:

And this is because I use one variable for all of them How can this be solved?

You already answered your question. You need a List of booleans or you add a isExpanded boolean in your signals object. If you have only variable, all the ExpansionPanels will behave the same.

You could do something like this:

List<bool> isExpanded = [];
for(int i = 0; i < _signals.length; i  ){
   isExpanded.add(false);
}

So every expanded panel is collapsed at first time.

Now in your ExpansionPanel you just read the bool at position index:

 isExpanded: isExpanded[index],

And to switch your expansion panel state just invert the bool at the position in the isExpanded list:

expansionCallback: (panelIndex, isExpanded) {
                              setState(() {
                                isExpanded[index] = !isExpanded[index];
                              });
                            },
  • Related