Flutter- ExpansionTile expand and collapse on click

后端 未结 3 1393
北荒
北荒 2020-12-10 07:06

I am taking this as a reference to expanding and collapsing of expansion tile-------Flutter - Collapsing ExpansionTile after choosing an item

What I want is if I one

相关标签:
3条回答
  • 2020-12-10 07:19

    You can use ExpandablePanelList to do perform expand and collapse view. Use expansionCallback to maintain active state to perform expand or collapse. here is the working example

    class TestExpandableView extends StatefulWidget {
      @override
      _TestExpandableViewState createState() => _TestExpandableViewState();
    }
    
    class _TestExpandableViewState extends State<TestExpandableView> {
      int _activeMeterIndex;
      @override
      Widget build(BuildContext context) {
        return Container(
          child: new ListView.builder(
              itemCount:  2,
              itemBuilder: (BuildContext context, int i) {
                return Card(
                  margin:
                  const EdgeInsets.fromLTRB(10.0, 15.0, 10.0, 0.0),
                  child: new ExpansionPanelList(
                    expansionCallback: (int index, bool status) {
                      setState(() {
                        _activeMeterIndex = _activeMeterIndex == i ? null : i;
                      });
                    },
                    children: [
                      new ExpansionPanel(
                          isExpanded: _activeMeterIndex == i,
                          headerBuilder: (BuildContext context,
                              bool isExpanded) =>
                          new Container(
                              padding:
                              const EdgeInsets.only(left: 15.0),
                              alignment: Alignment.centerLeft,
                              child: new Text(
                                'list-$i',
                              )),
                          body: new Container(child: new Text('content-$i'),),),
                    ],
                  ),
                );
              }),
        );
      }
    }
    
    0 讨论(0)
  • 2020-12-10 07:31

    I think you'll need to track the expansion state of each expansion tile individually. Something like:

    Map<String, bool> expansionState = Map();
    

    On initialization, you'll need to specify the keys and whether or not you want the associated expansion tile to show as opened or closed. In my code I have a List for the expansion tile names. On page load, I do the following:

    categoryList.forEach((name) {
       expansionState.putIfAbsent(name, () => true);
    });
    

    Then the builder simply refers to the expansionState:

    Widget _buildCategory(String name, List<OrderItem> children) {
        return ExpansionTile(
          key: PageStorageKey<String>(name),
          initiallyExpanded: expansionState[name], // true,
          title: RichText(
              text: TextSpan(
            text: name,
            style: TextStyle(
                color: Colors.blue[800], fontSize: 16, fontWeight: FontWeight.bold),
            children: <TextSpan>[
              TextSpan(
                  text: ' - ' + children.length.toString() + ' items',
                  style: TextStyle(
                      color: Colors.grey[800],
                      fontSize: 16,
                      fontWeight: FontWeight.normal)),
            ],
          )),
          onExpansionChanged: ((newState) {
            print(name + ' is now ' + newState.toString());
            expansionState[name] = newState;
          }),
          children: children.map<Widget>(_buildChild).toList(),
        );
      }
    

    At this point, you have the ability to add a button whose onPressed() method can manipulate the expansionState map any way you want inside of a setState() call. You could open them all, close them all, toggle their current states, etc.

    0 讨论(0)
  • 2020-12-10 07:38

    Instead of having to maintain the active state in expansionCallback like @Aravindh Kumar did, you can use ExpansionPanelList.radio which accepts a list of ExpansionPanelRadio as its children. This widget allows for at most one panel in the list to be open and maintains the active state for you automatically.

    Refer to the flutter documentation for example usage.

    // Flutter code sample for ExpansionPanelList.radio
    
    // Here is a simple example of how to implement ExpansionPanelList.radio.
    
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    /// This Widget is the main application widget.
    class MyApp extends StatelessWidget {
      static const String _title = 'Flutter Code Sample';
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: _title,
          home: Scaffold(
            appBar: AppBar(title: const Text(_title)),
            body: MyStatefulWidget(),
          ),
        );
      }
    }
    
    // stores ExpansionPanel state information
    class Item {
      Item({
        this.id,
        this.expandedValue,
        this.headerValue,
      });
    
      int id;
      String expandedValue;
      String headerValue;
    }
    
    List<Item> generateItems(int numberOfItems) {
      return List.generate(numberOfItems, (int index) {
        return Item(
          id: index,
          headerValue: 'Panel $index',
          expandedValue: 'This is item number $index',
        );
      });
    }
    
    class MyStatefulWidget extends StatefulWidget {
      MyStatefulWidget({Key key}) : super(key: key);
    
      @override
      _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
    }
    
    class _MyStatefulWidgetState extends State<MyStatefulWidget> {
      List<Item> _data = generateItems(8);
    
      @override
      Widget build(BuildContext context) {
        return SingleChildScrollView(
          child: Container(
            child: _buildPanel(),
          ),
        );
      }
    
      Widget _buildPanel() {
        return ExpansionPanelList.radio(
          initialOpenPanelValue: 2,
          children: _data.map<ExpansionPanelRadio>((Item item) {
            return ExpansionPanelRadio(
                value: item.id,
                headerBuilder: (BuildContext context, bool isExpanded) {
                  return ListTile(
                    title: Text(item.headerValue),
                  );
                },
                body: ListTile(
                    title: Text(item.expandedValue),
                    subtitle: Text('To delete this panel, tap the trash can icon'),
                    trailing: Icon(Icons.delete),
                    onTap: () {
                      setState(() {
                        _data.removeWhere((currentItem) => item == currentItem);
                      });
                    }));
          }).toList(),
        );
      }
    }
    
    0 讨论(0)
提交回复
热议问题