How to create Expandable ListView in Flutter
Try this:
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: MyApp(), debugShowCheckedModeBanner: false,),);
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: vehicles.length,
itemBuilder: (context, i) {
return ExpansionTile(
title: Text(vehicles[i].title, style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold, fontStyle: FontStyle.italic),),
children: <Widget>[
Column(
children: _buildExpandableContent(vehicles[i]),
),
],
);
},
),
);
}
_buildExpandableContent(Vehicle vehicle) {
List<Widget> columnContent = [];
for (String content in vehicle.contents)
columnContent.add(
ListTile(
title: Text(content, style: TextStyle(fontSize: 18.0),),
leading: Icon(vehicle.icon),
),
);
return columnContent;
}
}
class Vehicle {
final String title;
List<String> contents = [];
final IconData icon;
Vehicle(this.title, this.contents, this.icon);
}
List<Vehicle> vehicles = [
Vehicle(
'Bike',
['Vehicle no. 1', 'Vehicle no. 2', 'Vehicle no. 7', 'Vehicle no. 10'],
Icons.motorcycle,
),
Vehicle(
'Cars',
['Vehicle no. 3', 'Vehicle no. 4', 'Vehicle no. 6'],
Icons.directions_car,
),
];
Try this:
First Make an ExpandableContainer using AnimatedContainer.
Then Make an ExpandableListView which will create a Column . The first child of Column will be a button to expand and Second will be ExpandableContainer . ExpandableContainer will have a ListView as its child.
The last step will be to make a ListView of ExpandableListView.
The Result :
The Code :
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new Home()));
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.grey,
appBar: new AppBar(
title: new Text("Expandable List"),
backgroundColor: Colors.redAccent,
),
body: new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new ExpandableListView(title: "Title $index");
},
itemCount: 5,
),
);
}
}
class ExpandableListView extends StatefulWidget {
final String title;
const ExpandableListView({Key key, this.title}) : super(key: key);
@override
_ExpandableListViewState createState() => new _ExpandableListViewState();
}
class _ExpandableListViewState extends State<ExpandableListView> {
bool expandFlag = false;
@override
Widget build(BuildContext context) {
return new Container(
margin: new EdgeInsets.symmetric(vertical: 1.0),
child: new Column(
children: <Widget>[
new Container(
color: Colors.blue,
padding: new EdgeInsets.symmetric(horizontal: 5.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new IconButton(
icon: new Container(
height: 50.0,
width: 50.0,
decoration: new BoxDecoration(
color: Colors.orange,
shape: BoxShape.circle,
),
child: new Center(
child: new Icon(
expandFlag ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
color: Colors.white,
size: 30.0,
),
),
),
onPressed: () {
setState(() {
expandFlag = !expandFlag;
});
}),
new Text(
widget.title,
style: new TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
)
],
),
),
new ExpandableContainer(
expanded: expandFlag,
child: new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new Container(
decoration:
new BoxDecoration(border: new Border.all(width: 1.0, color: Colors.grey), color: Colors.black),
child: new ListTile(
title: new Text(
"Cool $index",
style: new TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
),
leading: new Icon(
Icons.local_pizza,
color: Colors.white,
),
),
);
},
itemCount: 15,
))
],
),
);
}
}
class ExpandableContainer extends StatelessWidget {
final bool expanded;
final double collapsedHeight;
final double expandedHeight;
final Widget child;
ExpandableContainer({
@required this.child,
this.collapsedHeight = 0.0,
this.expandedHeight = 300.0,
this.expanded = true,
});
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return new AnimatedContainer(
duration: new Duration(milliseconds: 500),
curve: Curves.easeInOut,
width: screenWidth,
height: expanded ? expandedHeight : collapsedHeight,
child: new Container(
child: child,
decoration: new BoxDecoration(border: new Border.all(width: 1.0, color: Colors.blue)),
),
);
}
}
Screenshot:
Code:
class MyPage extends StatelessWidget {
List<Widget> _getChildren(int count, String name) => List<Widget>.generate(
count,
(i) => ListTile(title: Text('$name$i')),
);
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
ExpansionTile(
title: Text('List-A'),
children: _getChildren(4, 'A-'),
),
ExpansionTile(
title: Text('List-B'),
children: _getChildren(3, 'B-'),
),
],
),
);
}
}