Flutter- ExpansionTile expand and collapse on click
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'),),),
],
),
);
}),
);
}
}
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(),
);
}
}