Reputation:
I have a list of Models:
class Model {
final DateTime date;
final String text;
Model({this.date, this.text});
}
List<Model> _models = [
Model(date: DateTime(2018, 9, 1), text: 'Text1',),
Model(date: DateTime(2018, 9, 1), text: 'Text2',),
Model(date: DateTime(2018, 9, 2), text: 'Text3',),
Model(date: DateTime(2018, 9, 3), text: 'Text4',),
Model(date: DateTime(2018, 8, 31), text: 'Text7',),
Model(date: DateTime(2018, 9, 3), text: 'Text5',),
Model(date: DateTime(2018, 9, 3), text: 'Text6',),
];
What I am trying to achieve is to take the date parameter from each model and put all models that match that date into a ListView(). So I can return a list of models for each date. Every time I add data to the list I want it to update & sort by date automatically (no manual stuff). Date formatting is not important here. Question: how can I achieve that?
Here is how I want it to look like:
2018/9/3
Text4
Text5
Text6
2018/9/2
Text3
2018/9/1
Text1
Text2
2018/8/31
Text7
Upvotes: 3
Views: 4120
Reputation: 489
For another bare-bone example involving no third-party packages:
import 'package:flutter/material.dart';
class Model {
final DateTime date;
final String text;
Model({this.date, this.text});
}
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Sample App',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// Populate initial value for the list of models
List<Model> _models = [
Model(
date: DateTime(2018, 9, 1),
text: 'Text1',
),
Model(
date: DateTime(2018, 9, 1),
text: 'Text2',
),
Model(
date: DateTime(2018, 9, 2),
text: 'Text3',
),
Model(
date: DateTime(2018, 9, 3),
text: 'Text4',
),
Model(
date: DateTime(2018, 8, 31),
text: 'Text7',
),
Model(
date: DateTime(2018, 9, 3),
text: 'Text5',
),
Model(
date: DateTime(2018, 9, 3),
text: 'Text6',
)
];
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Sample App"),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.plus_one),
onPressed: () {
setState(() {
// On click of floating action button, add a hardcoded item to _models list
_models.add(Model(
date: DateTime(2018, 9, 2),
text: 'New Item',
));
});
},
),
body: SortedGroupedList(_models),
);
}
}
class SortedGroupedList extends StatefulWidget {
final List<Model> list;
SortedGroupedList(this.list);
@override
State<StatefulWidget> createState() => _SortedGroupedListState();
}
class _SortedGroupedListState extends State<SortedGroupedList> {
List<Model> _list;
@override
void initState() {
super.initState();
_list = widget.list;
}
@override
Widget build(BuildContext context) {
_list.sort((a, b) => b.date.compareTo(a.date));
Model prev;
bool shownHeader = false;
List<Widget> _listChildren = <Widget>[];
_list.forEach((Model model) {
if (prev != null && model.date != prev.date) {
shownHeader = false; // if dates are different, beginning of a new group, so header is yet to be shown
}
if (!shownHeader) {
// if header for a group is not shown yet, add it to the list
_listChildren.add(ListTile(
title: Text(
model.date.toString(),
style: TextStyle(fontWeight: FontWeight.bold),
)));
prev = model; // keep the current model for reference to check if group has changed
shownHeader = true;
}
_listChildren.add(ListTile(title: Text(model.text)));
});
return ListView(children: _listChildren);
}
}
In this example, we create a new widget called SortedGroupedList
, which will accept the models list and sort it in descending order, then display it using a ListView, while keeping track of items grouped by their dates.
Also the onPress
of FloatingActionButton
will add one more hard-coded item to the list when floating action buton is pressed, and that is reflected with 'no manual stuff
' (whatever that is ;) ). This example can be improved to manipulate _model
list and all the changes should ideally be reflected on our view.
Note that, this example may not be ideal for a huge list as the list have to be sorted everytime any changes are made to it. A better approach may be using the ListView.builder(), but that can get complex depending on the operations you want to perform on the list.
Upvotes: 1
Reputation: 489
For an easy solution using an existing widget; you may use side_header_list_view (https://pub.dartlang.org/packages/side_header_list_view)
example :
Widget _buildList(){
return new SideHeaderListView(
itemCount: _models.length,
itemExtend: 100.0,
headerBuilder: (BuildContext context, int index) {
return Text(_models[index].date);
},
itemBuilder: (BuildContext context, int index) {
return new Card(
child: Text(_models[index].text),
);
},
hasSameHeader: (int a, int b) {
return _models[a].date == _models[b].date;
},
);
}
Haven't tested it, Ideally should work, provided, you might need to do some formatting of date to string type before giving it to Text.. Consider it like a pseudo code for now.
Upvotes: 2