Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create Expandable ListView in Flutter

How to make an Expandable ListView using Flutter like the screenshot below?

I want to make a scrollable list view of ExpansionTileswhich when expanded shows a non-scrollable list view.

I tried to implement list view of ExpansionTiles inside which I nested another list view using listView.builder(...). But when I expanded the ExpansionTile the list view didn't show up...

Expandable ListView

(The screenshot is for illustrative purpose)

Is there a way to get similar output in Flutter?

EDIT: My Source Code:

import 'package:flutter/material.dart';  void main() => runApp(   new MaterialApp(     home: new MyApp(),   ) );  var data = {   "01/01/2018": [     ["CocaCola", "\$ 5"],     ["Dominos Pizza", "\$ 50"],   ],    "04/01/2018": [     ["Appy Fizz", "\$ 10"],     ["Galaxy S9+", "\$ 700"],     ["Apple iPhone X", "\$ 999"],   ], };  List<String> dataKeys = data.keys.toList();  String getFullDate(String date) {   List<String> dateSplit = date.split('/');   List<String> months = ["Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec"];    return "${dateSplit[0]} ${months[int.parse(dateSplit[1]) - 1]} ${dateSplit[2]}"; }  class MyApp extends StatefulWidget {   @override   _MyAppState createState() => new _MyAppState(); }  class _MyAppState extends State<MyApp> {   List<Widget> _buildList(int keyIndex) {     List<Widget> list = [];      for (int i = 0; i < data[dataKeys[keyIndex]].length; i++) {       list.add(         new Row(           children: <Widget>[             new CircleAvatar(               child: new Icon(Icons.verified_user),               radius: 20.0,             ),             new Text(data[dataKeys[keyIndex]][i][0])           ],         )       );     }      return list;   }    @override   Widget build(BuildContext context) {     return new Scaffold(       appBar: new AppBar(         title: new Text("Expense Monitor"),       ),       body: new Container (         child: new ListView.builder(           itemCount: dataKeys.length,           itemBuilder: (BuildContext context, int keyIndex) {             return new Card(               child: new ExpansionTile(                 title: new Text(getFullDate(dataKeys[keyIndex])),                 children: <Widget>[                   new Column(                     children: _buildList(keyIndex)                   )                 ]               ),             );           }         )       )     );   } } 

Error as shown in Console:

I/flutter (12945): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════ I/flutter (12945): The following assertion was thrown during performResize(): I/flutter (12945): Vertical viewport was given unbounded height. I/flutter (12945): Viewports expand in the scrolling direction to fill their container.In this case, a vertical I/flutter (12945): viewport was given an unlimited amount of vertical space in which to expand. This situation I/flutter (12945): typically happens when a scrollable widget is nested inside another scrollable widget. I/flutter (12945): If this widget is always nested in a scrollable widget there is no need to use a viewport because I/flutter (12945): there will always be enough vertical space for the children. In this case, consider using a Column I/flutter (12945): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size I/flutter (12945): the height of the viewport to the sum of the heights of its children. I/flutter (12945): When the exception was thrown, this was the stack: I/flutter (12945): #0      RenderViewport.performResize.<anonymous closure> (package:flutter/src/rendering/viewport.dart:944:15) I/flutter (12945): #1      RenderViewport.performResize (package:flutter/src/rendering/viewport.dart:997:6) I/flutter (12945): #2      RenderObject.layout (package:flutter/src/rendering/object.dart:1555:9) I/flutter (12945): #3      _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:109:13) ...... I/flutter (12945): ════════════════════════════════════════════════════════════════════════════════════════════════════ I/flutter (12945): Another exception was thrown: RenderBox was not laid out: RenderViewport#df29c NEEDS-LAYOUT NEEDS-PAINT 
like image 262
Melvin Abraham Avatar asked May 25 '18 13:05

Melvin Abraham


People also ask

How do you make an expandable list view in flutter?

Expandable ListView is a type of list view that is used to show multiple types of data based on category and subcategory. Expandable list view is used to expand or collapse the view in list items In a flutter app. We can easily make our own Expandable ListView using the ExpansionTile widget.

How do you use expansion tiles in flutter?

You need to implement it in your code respectively: Create a new dart file called expansion_title_demo. dart inside the lib folder. In this screen, we will create a list with the help of a list view builder in which the expansion tile widget will be used and initialize the list data into the expansion tile widget.

What is expanded in flutter?

A widget that expands a child of a Row, Column, or Flex so that the child fills the available space. Using an Expanded widget makes a child of a Row, Column, or Flex expand to fill the available space along the main axis (e.g., horizontally for a Row or vertically for a Column).


2 Answers

Try this:

import 'package:flutter/material.dart';  void main() => runApp(new MaterialApp(home: new MyApp(), debugShowCheckedModeBanner: false,),);  class MyApp extends StatefulWidget {   @override   _MyAppState createState() => new _MyAppState(); }  class _MyAppState extends State<MyApp> {   @override   Widget build(BuildContext context) {     return new Scaffold(       body: new ListView.builder(         itemCount: vehicles.length,         itemBuilder: (context, i) {           return new ExpansionTile(             title: new Text(vehicles[i].title, style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold, fontStyle: FontStyle.italic),),             children: <Widget>[               new Column(                 children: _buildExpandableContent(vehicles[i]),               ),             ],           );         },       ),     );   }    _buildExpandableContent(Vehicle vehicle) {     List<Widget> columnContent = [];      for (String content in vehicle.contents)       columnContent.add(         new ListTile(           title: new Text(content, style: new TextStyle(fontSize: 18.0),),           leading: new 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 = [   new Vehicle(     'Bike',     ['Vehicle no. 1', 'Vehicle no. 2', 'Vehicle no. 7', 'Vehicle no. 10'],     Icons.motorcycle,   ),   new Vehicle(     'Cars',     ['Vehicle no. 3', 'Vehicle no. 4', 'Vehicle no. 6'],     Icons.directions_car,   ), ]; 
like image 52
Vinoth Kumar Avatar answered Sep 24 '22 06:09

Vinoth Kumar


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 :

ExpandableLIstView

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)),       ),     );   } } 
like image 23
Ajay Kumar Avatar answered Sep 26 '22 06:09

Ajay Kumar