How to Increment and Decrements single item in a List View in Flutter? - flutter

In my products Screen I have two buttons + and - for quantity,
these two buttons in my ListView it Increment/Decrement the whole list , I want to increment or decrement quantity upon button click for single list item. If I increase or decrease the counter it increment in every list item.
StreamController _event =StreamController<int>.broadcast();
int _counter = 0;
void initState() {
super.initState();
_event.add(0);
}
#override
Widget build(BuildContext context) {
.
.
return Scaffold(
body: allItemsFlowlist(),
);
}
Widget allItemsFlowlist(){
return Container(
child: ListView.builder(
itemCount: items.documents.length,
physics: AlwaysScrollableScrollPhysics(parent: BouncingScrollPhysics()),
itemBuilder: (context, i) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
flex: 3,
child: Row(
children: <Widget>[
Flexible(
flex: 4,
child: Container(
child: Row(
children: <Widget>[
Container(
width: 35,
height: 35,
decoration: BoxDecoration(
color: colorPallet('vprice_sectionIncrementerBackground'),
borderRadius: BorderRadius.circular(5),
),
child: IconButton(
icon: Icon(Icons.remove),
onPressed: _decrementCounter,
iconSize: 18,
color: colorPallet('vprice_sectionDecrementerBackground')
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Container(
width: 35,
height: 35,
decoration: BoxDecoration(
border: Border.all(
color: colorPallet('vprice_sectionIncrementerBackground'), //Color(0xFFFFD500),
width: 2,
),
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: StreamBuilder<int>(
stream: _event.stream,
builder: (context, snapshot) {
return Text(
_counter.toString(),
style: TextStyle(
color: colorPallet('vprice_sectionTextTextStyle4'),
fontSize: 16,
fontWeight: FontWeight.w500,
),
);
}),
),
),
),
Container(
width: 35,
height: 35,
decoration: BoxDecoration(
color: colorPallet('vprice_sectionIncrementerBackground'),
borderRadius: BorderRadius.circular(5),
),
child: IconButton(
icon: Icon(Icons.add),
onPressed: _incrementCounter,
iconSize: 18,
color: colorPallet('vprice_sectionDecrementerBackground'),
),
),
],
)),
),
Incrementer:
_incrementCounter() {
_counter++;
_event.add(_counter);
}
Decrementer:
_decrementCounter() {
if (_counter <= 0) {
_counter = 0;
} else {
_counter--;
}
_event.add(_counter);
}

Turn _counter into a list and add an item for each item in your listView.builder to it.
And when changing, change _counter [i];
And so will change that specific item!
List<int> _counter = List();
ListView.builder(
itemCount: items.documents.length,
physics: AlwaysScrollableScrollPhysics(parent: BouncingScrollPhysics()),
itemBuilder: (context, i) {
if(_counter.length < items.documents.length){
_counter.add(0);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
[...]
child: IconButton(
icon: Icon(Icons.remove),
onPressed: (){_decrementCounter(i);},
iconSize: 18,
color: colorPallet('vprice_sectionDecrementerBackground')
),
),
[...]
child: IconButton(
icon: Icon(Icons.add),
onPressed: (){_incrementCounter(i);},
iconSize: 18,
color: colorPallet('vprice_sectionDecrementerBackground'),
),
),
],
)),
),
[...]
_incrementCounter(int i) {
_counter[i]++;
_event.add(_counter[i]);
}
_decrementCounter(int i) {
if (_counter[i] <= 0) {
_counter[i] = 0;
} else {
_counter[i]--;
}
_event.add(_counter[i]);
}
Hope this helps!

Related

Screen does not update even though build function is running flutter

So I have created a chat app which draws from a pusher client. Whenever there is a new message, the build function does rebuild, and I believe the widget list does change, but there is no update on the screen. How do I fix this ?
Widget build(BuildContext context) {
// print(messageWidgetList.length);
return Scaffold(
backgroundColor: AppColors.lightGrey,
appBar: AppBar(
backgroundColor: Colors.transparent,
title: Text(
messageTo,
style: TextStyle(
color: AppColors.white,
fontSize: 22,
),
),
),
body: Stack(
children: [
Padding(
padding:
const EdgeInsets.only(top: 12, left: 12, right: 12, bottom: 70),
child: ValueListenableBuilder<List<Widget>>(
valueListenable: messageWidgetList,
builder: (context, value, widget) {
print("Updated");
print(value.length);
// print(widget);
return ListView.builder(
// controller: scrollController,
physics: AlwaysScrollableScrollPhysics(),
reverse: true,
addAutomaticKeepAlives: true,
itemCount: value.length,
itemBuilder: (ctx, index) {
// print(index);
return value[index];
},
);
},
),
),
Align(
alignment: Alignment.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (xFilesImages.isNotEmpty)
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: xFilesImages.map<Widget>((element) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: SizedBox(
height: 100,
width: 80,
child: Image.file(
File(element.path),
frameBuilder:
(ctx, child, frame, wasSynchronouslyLoaded) {
return SizedBox(
width: MediaQuery.of(ctx).size.width,
height: MediaQuery.of(ctx).size.height,
child: Stack(
children: [
Align(
alignment: Alignment.topRight,
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColors.lightestGrey,
),
child: FittedBox(
child: GestureDetector(
onTap: () {
xFilesImages.remove(element);
setState(() {});
},
child:
const Icon(Icons.cancel)),
),
),
),
child
],
),
);
},
),
),
);
}).toList(),
),
),
const SizedBox(height: 5),
Container(
height: 60,
width: MediaQuery.of(context).size.width,
child: Padding(
padding:
const EdgeInsets.only(left: 10, bottom: 10, right: 10),
child: Container(
// height: 30,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: AppColors.darkGrey,
),
child: TextFormField(
// expands: true,
style: TextStyle(color: AppColors.white),
focusNode: messageFocusNode,
controller: messageController,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(
right: 8, left: 8, top: 14),
prefixIcon: InkWell(
onTap: () async {
if (!(await Permission.camera.isGranted)) {
await Permission.camera.request();
await Permission.photos.request();
}
ImagePicker _picker = ImagePicker();
xFilesImages =
await _picker.pickMultiImage() ?? [];
print("Got xFiles");
print(xFilesImages.length);
for (XFile xFile in xFilesImages) {
print(xFile.name);
print(xFile.path);
}
setState(() {});
},
child: Icon(
Icons.attachment,
size: 34,
color: AppColors.lightestGrey,
),
),
suffixIcon: GestureDetector(
onTap: () async {
//TODO: When you wake up, you have implemented picking images. Work on displaying picked images and then sending them
// loading = true;
// messageController.text = '';
if (messageController.text.isNotEmpty ||
xFilesImages.isNotEmpty) {
messageFocusNode.unfocus();
// messageWidgetList.add(sentMessage(
// {"message": messageController.text}));
setState(() {});
print("Sent button clicked");
ApiProvider.sendMessage(
widget.userModel.bearerToken,
widget.senderPhone.phoneNumbers.first,
messageTo,
messageController.text,
xFilesImages);
// loading = false;
messageController.text = '';
xFilesImages = [];
setState(() {});
}
},
child: const Icon(
Icons.send,
size: 30,
color: const Color(0xFF004b77),
),
),
fillColor: AppColors.lightGrey,
hintText: "Enter message...",
hintStyle:
TextStyle(color: AppColors.lightestGrey)),
),
),
),
),
],
),
),
if (loading)
Container(
height: double.infinity,
width: double.infinity,
color: AppColors.lightGrey.withOpacity(0.3),
child: Center(
child: SpinKitChasingDots(
color: AppColors.blue,
)),
)
],
),
);
}
Bad, does not work
static final List<Widget> items= [];
Widget build(BuildContext context) {
return ListView(children: items); // <-- look here
}
Good, does update properly
static final List<Widget> items= [];
Widget build(BuildContext context) {
return ListView(children: [...items]); // <-- look here
}
Grandious with the little extra mile
static final List<Widget> items= [];
Widget build(BuildContext context) {
return ListView(children: <Widget>[...items]); // <-- look here
}
setState needs a brand new object to update properly. It does not look into a List like here if something changed in there.

Listview not showing on startup but shows after rebuilding/refreshing - Flutter

I need some help please. On startup, everything loads except the listview. When I do anything on the page the listview appears. Feels like a refresh/rebuild issue. How do I tell it to refresh the listview? I don't know where to maybe use setState (doesn't work in Scaffold)
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildBar(context),
body: HouseLayout(),
);}
class HouseLayout extends StatefulWidget {
#override
HouseLayoutState createState() {
return HouseLayoutState();
}
}
class HouseLayoutState extends State<HouseLayout> with TickerProviderStateMixin {
#override
Widget build(BuildContext context) {
int y = 0;
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(taal.HuisTitle,
style: TextStyle(
fontWeight: FontWeight.normal,
color: Colors.white,
fontSize: 28,
)),
backgroundColor: Color.fromRGBO(61, 147, 243, 1.0)),
body: Stack(alignment: Alignment.bottomLeft, children: [
Column(children: [
Expanded(
flex: 10,
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (context, indexA) {
var kasNaam = kaste[indexA];
return Padding(
padding: EdgeInsets.all(0.0),
child: Column(children: <Widget>[
Card(
color: Color.fromRGBO(96, 166, 243, 1.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'$kasNaam',
style: TextStyle(
fontWeight: FontWeight.normal,
color: Colors.white,
fontSize: 20,
),
),
),
Container(
child: Row(
children: [
IconButton(
icon: Icon(Icons.edit,
color: Colors.white),
onPressed: () {
setState(() {
_editKasDialog(indexA);
});
}),
IconButton(
icon: Icon(Icons.delete,
color: Colors.white),
onPressed: () {
setState(() {
for (int i = 0;
i < kruideniers.length;
i++) {
if (kruideniers[i].kas ==
kaste[indexA]) {
y++;
}
}
if (y != 0) {
_deleteNotPossibleDialog(y);
}
if (y == 0) {
_deleteKasConfirmDialog(indexA);
}
});
}),
],
),
),
]),
),
_isSearching
? _buildSearchList(context, kasNaam)
: _bouKruideniersLys(context, kasNaam),
]),
);
},
itemCount: kaste.length,
)),
Container(height: 40),
]),
Container(color: Color.fromRGBO(61, 147, 243, 1.0), height: 40),
Positioned(
bottom: 0,
right: 0,
child: Stack(children: [
Container(width: 300, height: 350),
Positioned(...),
Positioned(...),
Positioned(...),
Positioned(...),
Positioned(...),
Container(width: 5, height: 5),
Padding(
padding: const EdgeInsets.all(8.0),
child: FloatingActionButton(
elevation: 5,
shape: CircleBorder(),
backgroundColor: Color.fromRGBO(16, 124, 243, 1.0),
child: SizedBox(
width: 56,
height: 56,
child: Icon(Icons.shopping_cart,
size: 35, color: Colors.white)),
splashColor: Colors.yellow,
onPressed: () {
setState(() {
Navigator.pushNamed(context, '/shop');
});
},
heroTag: null)),
],
),
),
]),
)
]));
}
Any help will be great! Thanks
I read kaste list from a txt file:
List<String> kaste = [];
void readFileH() async {
final fileH = await findFileH();
List<String> contents = await fileH.readAsLines();
String kas;
for (int i = 0; i < contents.length; i++) {
kas = contents[i].substring(0, contents[i].indexOf("#"));
contents[i] = contents[i].replaceRange(0, contents[i].indexOf("#") + 1, "");
kaste.add(kas);
}
kaste.sort();
}
Hi the problem is that the data is null when flutter render the ListView because the data isn't loaded, you need to use a wrap your ListView into a future builder, while the data is loading you can put a image or a circular progress indicator, when the data is loaded you render the elements into a ListView

Flutter : serState() or markNeedBuild() called during build

I have a widget which used to select a date, at beginning it's with 'no date chosen', and the widget in a column below it depends on it [which mean its show a list of timeSlots of Data if I selected a date]
But I got a setState called during build error, and This ReservationSlotWidget can not be marked as needing to build because the Framework is already in the process of building widgets
This is the selectDate widget
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Icon(
Icons.date_range,
color: Colors.white,
),
SizedBox(
width: 5,
),
Text(
_formatted == null
? 'No date chosen'
: _formatted,
style: TextStyle(
color: Colors.white,
))
],
),
FlatButton(
onPressed: ()=>_selectReservationDate(context),
child: Text(
'choose Date',
style: TextStyle(
color: Colors.white,
decoration: TextDecoration.underline),
),
)
],
),
if(_selectedDate != null)
Divider(
color: parseColor('#2A2E43'),
thickness: 2.0,
),
if(_selectedDate != null)
Row(
children: <Widget>[
Icon(
Icons.alarm,
color: Colors.white,
),
SizedBox(
width: 5,
),
Text('$_numberOfSeats Available Time Slots',
style: TextStyle(
color: Colors.white,
))
],
),
this is a listview items which appeared depend on the date I chose.
if(_formatted != null)
Expanded(
child: Consumer<SlotProvider>(
builder: (ctx, slotProvider, _)=>
ListView.builder(
itemCount: slotProvider.slots.length,
scrollDirection: Axis.horizontal,
itemBuilder: (ctx, index) {
setState(() {
_numberOfSeats = slotProvider.slots[index].seats;
});
return GestureDetector(
onTap: () {
setState(() {
if(_isInit){
_isExpanded = !_isExpanded;
}
_expandedIndex = index;
_isInit = false;
});
},
child: Container(
padding: EdgeInsets.all(4),
margin: EdgeInsets.all(4),
decoration: BoxDecoration(
color: _expandedIndex == index
? Theme.of(context).primaryColor
: parseColor('#2A2E43'),
borderRadius:
BorderRadius.all(Radius.circular(10))),
child: SlotsWidget(
fromTime: slotProvider.slots[index].fromTime.toString(),
toTime:slotProvider.slots[index].toTime.toString(),
seats:slotProvider.slots[index].seats,
))
);
}
),
)
),
the comment of #void is right and you can avoid the repeated setState with if block;
if (_numberOfSeats != slotProvider.slots[index].seats)
setState(() {
_numberOfSeats = slotProvider.slots[index].seats;
});

Why is selected value not reflecting in showModalBottomSheet with flutter?

First of all, I created a designed bottom sheet, In which, there are two lists to show numbers(left side) and options(hour, day, week, month) with the help of CupertinoPicker widget,
Numbers will depend on what option I select, If I select the hour, numbers of the left side should be 1-24, and if I select week, numbers should be 1-4, I select the day, numbers should be 1-30 and last I select month number should be 1-12.
Code :
All Lists variable:
List<String> reminderDay = ['hour','day','week','month'];
List<String> reminderHoursVal =['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24'];
List<String> reminderDaysVal =['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31'];
List<String> reminderMonthsVal =['1','2','3','4','5','6','7','8','9','10','11','12'];
List<String> reminderWeeksVal =['1','2','3','4'];
String selectedReminderVal='1';
String selectedReminderDay ='hour';
Code of bottom sheet:
addReminder(){
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return AnimatedPadding(
padding: MediaQuery.of(context).viewInsets,
duration: const Duration(milliseconds: 100),
curve: Curves.decelerate,
child: Container(
padding: const EdgeInsets.only(top:8,right: 8, left:8,bottom: 8),
height: MediaQuery.of(context).size.height/2,
// color: Colors.transparent,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30)
)
),
child: Container(
child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height:10),
Text("Set a reminder",
style: TextStyle(
fontSize:18,
fontWeight:FontWeight.bold,
color: Colors.grey
),
),
SizedBox(height:20),
Container(
margin: const EdgeInsets.only(left: 10, right: 10),
height: MediaQuery.of(context).size.height/4,
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(10)
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: CupertinoPicker(
scrollController: new FixedExtentScrollController(
initialItem: 0,
),
itemExtent: 30,
backgroundColor: Colors.grey[100],
onSelectedItemChanged: (int val) {
setState(() {
if(selectedReminderDay=='day'){
selectedReminderVal = reminderDaysVal[val];
}else if(selectedReminderDay=='week'){
selectedReminderVal = reminderWeeksVal[val];
}else if(selectedReminderDay=='month'){
selectedReminderVal = reminderMonthsVal[val];
}else{
selectedReminderVal = reminderHoursVal[val];
}
print("selectedReminderVal:$selectedReminderVal");
});
},
children:selectedReminderDay=='day'?reminderDaysVal
:selectedReminderDay=='week'?reminderWeeksVal
:selectedReminderDay=='month'?reminderMonthsVal:reminderHoursVal// ['hour','day','week','month']; reminderHoursVal
.map(
(item) => Center(
child: Text(
item,
style: TextStyle(
fontSize: 16,
// fontWeight:FontWeight.bold,
),
),
),
)
.toList()),
),
Expanded(
child: CupertinoPicker(
scrollController: new FixedExtentScrollController(
initialItem: 0,
),
itemExtent: 30,
backgroundColor: Colors.grey[100],
onSelectedItemChanged: (int val) {
setState(() {
selectedReminderDay = reminderDay[val];
print("selectedReminderDay:$selectedReminderDay");
});
},
children: reminderDay
.map(
(item) => Center(
child: Text(
item,
style: TextStyle(
fontSize: 16,
// fontWeight:FontWeight.bold,
),
),
),
)
.toList()),
),
])
),
SizedBox(height:15),
// selectedVal!=null?Text(selectedVal.toString()):Container()
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("You'll get the reminder"),
Text('$selectedReminderVal $selectedReminderDay before the event')
],
),
SizedBox(height:25),
Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: (){
Navigator.pop(context);
},
child: Text("Cancel",
style: TextStyle(
fontSize: 18,
color: Colors.blue,
fontWeight: FontWeight.bold
),
),
),
InkWell(
onTap: (){
Navigator.pop(context);
},
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8)
),
width: MediaQuery.of(context).size.width/5,
height: MediaQuery.of(context).size.height/25 ,
child: Text("Save", style:TextStyle(
color: Colors.white,
fontSize: 19
)),
),
)
],
),
)
],
),
)
),
);
},
);
}
Screenshot:
This is because the state you are setting is different from the state in the modal bottom sheet.
Right now, when you are calling setState, you are actually rebuilding the stateful widget under the modal bottom sheet.
To fix this, just wrap your bottom sheet in a Stateful Builder.
StatefulBuilder(
builder: (context, setState) {
return AnimatedPadding(
padding: MediaQuery.of(context).viewInsets,
duration: const Duration(milliseconds: 100),
curve: Curves.decelerate,
child: Container(
padding: const EdgeInsets.only(top:8,right: 8, left:8,bottom: 8),
height: MediaQuery.of(context).size.height/2,
// color: Colors.transparent,
decoration: BoxDecoration(
color: Colors.white,
....
when we create new context widgets in existing state there states become different, bottomSheets are similar to dialogBox with new context and builder build a completely new widget out of the parent state, to create its own stateful state Wrap it with the stateful builder and user its own setState to change anything in this context not the parent one
eg:
StatefulBuilder(
builder: (context, setStateChild) {
return AnimatedPadding(...
Expanded(
child: CupertinoPicker(
scrollController: new FixedExtentScrollController(
initialItem: 0,
),
itemExtent: 30,
backgroundColor: Colors.grey[100],
onSelectedItemChanged: (int val) {
setStateChild(() {
selectedReminderDay = reminderDay[val];
print("selectedReminderDay:$selectedReminderDay");
});
},);
child: ... ),
}

List.Builder giving range error in Flutter

I have added my entire code over here. The getRecords method takes more time to add to the lists and hence my list returns empty at first and so listbuilder fails giving range error and that only range accepted is 0. BTW, Its a Todo app.
InitState :
void initState() {
super.initState();
setState(() {
getRecords();
});
}
Getting from the database
void getRecordsAndDisplay() async {
final records = await Firestore.instance.collection('tasks').getDocuments();
for (var record in records.documents) {
if (record.data['phone'] == '1') {
int len = record.data['task'].length;
if (len != null || len != 0) {
for (int i = 0; i < len; i++) {
String temp = record.data['task'][i];
tasks.add(temp);
}
}
else
continue;
}
else
continue;
}
setState(() {
listView = ListView.builder(
scrollDirection: Axis.vertical,
itemCount: tasks.length,
itemBuilder: (BuildContext context,int index) {
return Container(
margin: EdgeInsets.only(bottom: 10.0),
decoration: BoxDecoration(
color: Colors.deepPurple[700],
borderRadius: BorderRadius.all(Radius.circular(20.0)),
),
child: ListTile(
onTap: (){},
leading: IconButton(
icon: Icon(Icons.delete),
iconSize: 25.0,
color: Colors.white,
onPressed: () {
setState(() {
tasks.removeAt(index);
checkValue.removeAt(index);
updateValue();
});
},
),
title: Text(
'${tasks[index]}',
style: TextStyle(
fontSize: 18.0,
color: Colors.white,
fontWeight: FontWeight.bold,
decoration: checkValue[index]
? TextDecoration.lineThrough
: null,
),
),
trailing: Checkbox(
value: checkValue[index],
activeColor: Colors.white,
checkColor: Colors.deepPurple[700],
onChanged: (bool value) {
setState(() {
checkValue[index] = !checkValue[index];
});
},
),
),
);
},
);
});
}
Scaffold:
return Scaffold(
backgroundColor: Color(0xff8780FF),
body: SafeArea(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
colors: [Colors.deepPurple[400], Color(0xff6B63FF)])),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(30.0, 30.0, 30.0, 15.0),
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
spreadRadius: 1.0,
blurRadius: 50.0,
),
]),
child: Icon(
Icons.list,
color: Colors.white,
size: 30.0,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.only(
bottom: 20.0,
left: 30.0,
),
child: Text(
'Todo List',
style: TextStyle(
color: Colors.white,
fontSize: 35.0,
fontWeight: FontWeight.w900,
),
),
),
Expanded(
child: SizedBox(
width: 20.0,
),
),
IconButton(
padding: EdgeInsets.only(
right: 10.0,
bottom: 20.0,
),
icon: Icon(Icons.add),
iconSize: 30.0,
color: Colors.white,
onPressed: () async {
final resultText = await showModalBottomSheet(
context: context,
builder: (context) => AddTaskScreen(),
isScrollControlled: true);
setState(() {
tasks.add(resultText);
checkValue.add(false);
Firestore.instance
.collection('tasks')
.document('1')
.updateData({
'task': FieldValue.arrayUnion([resultText]),
});
});
},
),
IconButton(
padding: EdgeInsets.only(
right: 10.0,
bottom: 20.0,
),
icon: Icon(Icons.delete_outline),
iconSize: 30.0,
color: Colors.white,
onPressed: () {
setState(() {
tasks.clear();
checkValue.clear();
Firestore.instance
.collection('tasks')
.document('1')
.updateData({
'task': null,
});
});
},
),
],
),
],
),
Flexible(
child: Container(
padding: EdgeInsets.only(left: 10.0, right: 10.0),
height: MediaQuery.of(context).size.height,
child: listView,
),
),
],
),
),
),
);
Please help me out. I am stuck with this for a long time :(
the problem is that in initstate you cannot await for async methods so you should implement a StreamBuilder that wraps your listview..
A streambuilder is a widget that takes a stream and waits for the call completition then when the data is ok shows a widget -> your listview
A little example
StreamBuilder(
stream: YOUR_ASYNC_CALL_THAT_RETURN_A_STREAM,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Container(
alignment: Alignment.center,
child: Text(
"NO ITEMS"
),
);
}
else {
var yourList = snapshot.data.documents;//there you have to do your implementation
return ListView.builder(
itemBuilder: (context, index) => buildItem(index,yourList[index]),
itemCount: yourList.length,
);
}
},
),