How to Expand only one ExpansionTile at a time in Flutter
Asked Answered
D

4

5

I have built a Listview with ExpansionTile. But Now I want that if I tap on an ExpansionTile then only that ExpansionTile should open and other Expanded ExpansionTile should close.

Please help me how can I achieve this?

Here is my Code for ExpansionTile

   @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text("Short Product"),
            ),
            body: ListView.builder(
              itemCount: Category_List.length,
              itemBuilder: (context, i) {
                return ExpansionTile(
                  title: Text(Category_List[i].cat_name),
                  children:_Product_ExpandAble_List_Builder(Category_List[i].cat_id)
                );
              },
            )
         );
      }

      _Product_ExpandAble_List_Builder(int cat_id) {
        List<Widget> columnContent = [];
        Product_List.forEach((product) => {
                columnContent.add(
                  ListTile(
                    title: ExpansionTile(
                        title: Text(product.prod_name),
                        ),
                    trailing: Text("${product.total_Qty} (Kg)"),
                  ),
                ),
            });
        return columnContent;
      }
}

Thanks in advance.

Disorganization answered 14/5, 2020 at 6:36 Comment(3)
Just a little advice.. All variable should be formatted in camel case starting with lower case letter. I'm not sure if formatting variable names otherwise will have any affect on functionality of the app but most importantly it is the rule to format it that wayNessim
Just use a ExpansionPanelList.radio - it does what you want.Erastianism
You can have a controller for each expansion tile and then using the controller you can manage the collapse and expand state.Olomouc
C
10

you can programmatically change expansion tile should open or close.

I made similar to your code.

int selected; //attention

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Short Product"),
      ),
      body: ListView.builder(
        key: Key('builder ${selected.toString()}'), //attention
        itemCount: 10,
        itemBuilder: (context, i) {
          return ExpansionTile(
              key: Key(i.toString()), //attention
              initiallyExpanded: i == selected, //attention
              title: Text(i.toString()),
              children: _Product_ExpandAble_List_Builder(i),
              onExpansionChanged: ((newState) {
                if (newState)
                  setState(() {
                    selected = i;
                  });
                else
                  setState(() {
                    selected = -1;
                  });
              }));
        },
      ),
    );
  }

  _Product_ExpandAble_List_Builder(int cat_id) {
    List<Widget> columnContent = [];
    [1, 2, 4, 5].forEach((product) => {
          columnContent.add(
            ListTile(
              title: ExpansionTile(
                title: Text(product.toString()),
              ),
              trailing: Text("$product (Kg)"),
            ),
          ),
        });
    return columnContent;
  }
Confluent answered 14/5, 2020 at 6:48 Comment(3)
Nice workaround almost same as this one #59820765 I think the right answer should be no it is not possible unless you create your own expansion tile. The build in expansion tiles aren't design to do this. Using this workarounds will damage all animations so it is quite useless unless you don't mind design. I'm waiting for this feature long time to be implemented into flutter expansion tileNessim
Now i have a sublist how i can do this for that list??Disorganization
setState changes scroll position, Is there any way to get rid of it?Rigdon
A
5

There is widget from Flutter team for this:

ExpansionPanelList with its ExpansionPanelList.radio builder

See docs

https://api.flutter.dev/flutter/material/ExpansionPanelList/ExpansionPanelList.radio.html

Ardy answered 29/11, 2023 at 15:21 Comment(0)
S
0

Have you tried this https://pub.dev/packages/expansion_tile_list

its a container over the ExpansionTile, that means you don't have to change your widget.

var expansionTileList =
ExpansionTileList.radio(
  initialExpandedIndex: 0,
  children: <ExpansionTile>[
    ExpansionTile(
      title: Text('Tile 1'),
      children: <Widget>[Text('Child 1')],
    ),
    ExpansionTile(
      title: Text('Tile 2'),
      children: <Widget>[Text('Child 2')],
    ),
  ],
);

Disclaimer: I am the author

Schoolmaster answered 4/8, 2024 at 0:5 Comment(0)
T
0

One possible Solution is to have a Controller for each Tile, then use

ExpansionTile.onExpansionChanged: (value) {
   // Only close other Tiles when opening a new one.
   if (value) {
   // Other Controllers.collapse();
}

The positive is, it works as you want and actually uses Tiles not Panels, like the ExpansionPanelList.radio().
And you keep the expanding/collapsing Animations.

The Negative is, you have to store a ExpansionTileController for each Tile

Tibiotarsus answered 27/8, 2024 at 10:20 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.