RangeError (end): Invalid value: Not in inclusive range 0..17: 18 - flutter

I know there are alot of similar questions in the platoform but i just cant find similar soulitions to mine.
So my listview.builder in my streambuilder is working fine when I do not update the details of an item. But when i access the item detail page and update my item using a function i created in the item detail page. The details will get updated but when i return to the item list page with listview.builder in streambuilder. The error occurs ("RangeError (end): Invalid value: Not in inclusive range 0..17: 18"). I am not sure why this happens. Please help me.
This is my streambuilder page
Widget build(BuildContext context) {
return StreamProvider<List <Announcement>>.value(
value: DatabaseService(uid: ' ', docID: ' ', sort: '${isOldToNew}',aLevel: widget.selectionLevel,aType: widget.selectionType).announcementList,
initialData: [],
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Theme.of(context).primaryColor,
elevation: 0.0,
centerTitle: true,
),
body: Column(
children: <Widget>[
Expanded(
child: AnnouncementListForAll(),
),
],
),
),
);
}
My listview.builder is in the AnnouncementListForAll class in the expanded widget.
Below is my AnnouncementListForAll code.
Widget build(BuildContext context) {
final announcementList = Provider.of<List <Announcement>>(context);
return Scrollbar(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: announcementList.length,
itemBuilder: (context, index){
return announcementTileForAll(announcementlist: announcementList[index]);
},
),
);
}
This is my tile class in the listview.builder
class announcementTileForAll extends StatelessWidget {
final Announcement announcementlist;
announcementTileForAll({ required this.announcementlist });
#override
Widget build(BuildContext context) {
return Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(
horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(
color: Color.fromRGBO(64, 75, 96, .5)),
child: ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => announcementDetailForAll(announcementlist.id),
),
);
},
contentPadding: EdgeInsets.symmetric(
horizontal: 10.0, vertical: 10.0
),
title: Text(
announcementlist.title.length > 15 ? '${announcementlist.title.substring (0,18)} ...' : announcementlist.title, // limit the words that will be displayed out on screen
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold),
),
// subtitle: Text("10.07.2020", style: TextStyle(color: Colors.white)),
subtitle: Column(
children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.fromLTRB(0.0,2.0,0.0,0.0),
child: Text(announcementlist.content.length > 20 ? '${announcementlist.content.substring (0,20)} ... ' : announcementlist.content), // limit the words that will be displayed out on screen
),
),
Row(
children: <Widget>[
Icon(Icons.linear_scale,
color: Colors.yellowAccent),
Text(announcementlist.dateTime,
style: TextStyle(color: Colors.white)),
],
),
],
),
trailing: Icon(Icons.keyboard_arrow_right,
color: Colors.white, size: 30.0)),
),
);
}
}
Apparently i found out it is the substring issue, how can i solve this problem ?

Related

Flutter || Checkbox on hover doesn't give on tap cursor permission

I am working on dropdownmenu items where in the drop-down menu item there are several checkboxes but any of the checkboxes on hover don't give on tap cursor permission.
This is a very strange thing I found out as I have already used the checkbox before but this type of error I didn't receive.
I think maybe the problem is in dropdownmenu.
I have also included the video for better understanding of my problem.
my code :-
Container(
width: 160,
//margin: const EdgeInsets.only(top: 10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5), color: Colors.white),
child: ListTileTheme(
contentPadding: EdgeInsets.all(0),
dense: true,
horizontalTitleGap: 0.0,
minLeadingWidth: 0,
child: ExpansionTile(
iconColor: primaryBackgroundLightGrey,
title: Text(
listOFSelectedItem.isEmpty
? "Project type"
: listOFSelectedItem[0],
style: t5O40),
children: <Widget>[
Container(
height: 10,
color: primaryBackgroundLightGrey,
),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: widget.listOFStrings.length,
itemBuilder: (BuildContext context, int index) {
return Column(
children: [
Container(
height: 10,
),
Container(
margin: const EdgeInsets.only(bottom: 8.0),
child: _ViewItem(
item: widget.listOFStrings[index],
selected: (val) {
selectedText = val;
if (listOFSelectedItem.contains(val)) {
listOFSelectedItem.remove(val);
} else {
listOFSelectedItem.add(val);
}
widget.selectedList(listOFSelectedItem);
setState(() {});
},
itemSelected: listOFSelectedItem
.contains(widget.listOFStrings[index])),
),
],
);
},
),
],
),
),
),
class _ViewItem extends StatelessWidget {
String item;
bool itemSelected;
final Function(String) selected;
_ViewItem(
{required this.item, required this.itemSelected, required this.selected});
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
return Padding(
padding: EdgeInsets.only(
left: size.width * .015,
),
child: Row(
children: [
SizedBox(
height: 2,
width: 2,
child: Checkbox(
value: itemSelected,
onChanged: (val) {
selected(item);
},
hoverColor: Colors.transparent,
checkColor: Colors.white,
activeColor: Colors.grey),
),
SizedBox(
width: size.width * .010,
),
Text(item, style: t3O60),
],
),
);
}
}
You can adapt the example to your own code
dropdownBuilder: _customDropDownExample,
popupItemBuilder: _customPopupItemBuilderExample,
Widget _customDropDownExample(
BuildContext context, UserModel? item, String itemDesignation) {
if (item == null) {
return Container();
}
return Container(
child: (item.avatar == null)
? ListTile(
contentPadding: EdgeInsets.all(0),
leading: CircleAvatar(),
title: Text("No item selected"),
)
: ListTile(
contentPadding: EdgeInsets.all(0),
leading: CircleAvatar(
// this does not work - throws 404 error
// backgroundImage: NetworkImage(item.avatar ?? ''),
),
title: Text(item.name),
subtitle: Text(
item.createdAt.toString(),
),
),
);
After that
Widget _customPopupItemBuilderExample(
BuildContext context, UserModel item, bool isSelected) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 8),
decoration: !isSelected
? null
: BoxDecoration(
border: Border.all(color: Theme.of(context).primaryColor),
borderRadius: BorderRadius.circular(5),
color: Colors.white,
),
child: ListTile(
selected: isSelected,
title: Text(item.name),
subtitle: Text(item.createdAt.toString()),
leading: CircleAvatar(
// this does not work - throws 404 error
// backgroundImage: NetworkImage(item.avatar ?? ''),
),
),
);
I am using this package https://pub.dev/packages/dropdown_button2
Multiselect Dropdown with Checkboxes
final List<String> items = [
'Item1',
'Item2',
'Item3',
'Item4',
];
List<String> selectedItems = [];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: DropdownButtonHideUnderline(
child: DropdownButton2(
isExpanded: true,
hint: Align(
alignment: AlignmentDirectional.center,
child: Text(
'Select Items',
style: TextStyle(
fontSize: 14,
color: Theme.of(context).hintColor,
),
),
),
items: items.map((item) {
return DropdownMenuItem<String>(
value: item,
//disable default onTap to avoid closing menu when selecting an item
enabled: false,
child: StatefulBuilder(
builder: (context, menuSetState) {
final _isSelected = selectedItems.contains(item);
return InkWell(
onTap: () {
_isSelected
? selectedItems.remove(item)
: selectedItems.add(item);
//This rebuilds the StatefulWidget to update the button's text
setState(() {});
//This rebuilds the dropdownMenu Widget to update the check mark
menuSetState(() {});
},
child: Container(
height: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
children: [
_isSelected
? const Icon(Icons.check_box_outlined)
: const Icon(Icons.check_box_outline_blank),
const SizedBox(width: 16),
Text(
item,
style: const TextStyle(
fontSize: 14,
),
),
],
),
),
);
},
),
);
}).toList(),
//Use last selected item as the current value so if we've limited menu height, it scroll to last item.
value: selectedItems.isEmpty ? null : selectedItems.last,
onChanged: (value) {},
buttonHeight: 40,
buttonWidth: 140,
itemHeight: 40,
itemPadding: EdgeInsets.zero,
selectedItemBuilder: (context) {
return items.map(
(item) {
return Container(
alignment: AlignmentDirectional.center,
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
selectedItems.join(', '),
style: const TextStyle(
fontSize: 14,
overflow: TextOverflow.ellipsis,
),
maxLines: 1,
),
);
},
).toList();
},
),
),
),
);
}

Not able to get element index in a listview - Flutter

i'm trying to make operations on clicked elements in a listView in flutter. An alertDialog should appear once I click an element so I can update its value. My backend works perfectly using the put http method. The problem is that i'm able to read the input value in console but not able to read the index of the clicked element.
As it's mentionned above, i'm able to read the input value which means that my api works correctly, but not able to retrieve the clicked element's index in the listView.
Console output:
I/flutter ( 4120): ============================== null
I/flutter ( 4120): 33
here is my update function:
handleMeasurement(String iv_id, String value) async {
final response = await http.put(
Uri.parse('${baseUrl}/api/v1/measurements/update/' + iv_id),
body: <String, String>{
"input_value": value
});
}
and here is my ui:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text(
'Traitement des mesures',
style: TextStyle(color: Colors.black),
),
centerTitle: true,
),
body: Visibility(
visible: isLoaded,
replacement: Center(child: CircularProgressIndicator()),
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
padding: EdgeInsets.all(15),
itemCount: mesures?.length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () => showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('Mesure'),
content: TextField(
controller: _textFieldController,
decoration:
InputDecoration(hintText: "Entrez la valeur"),
),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'Cancel'),
child: const Text('Cancel'),
),
TextButton(
onPressed: () => {
print(
"============================== ${mesures![index].measurement_id}"),
print(_textFieldController.text),
handleMeasurement(
"${mesures![index].measurement_id}",
_textFieldController.text),
Navigator.pop(context, 'OK')
},
child: const Text('OK'),
),
],
),
),
child: Container(
margin: EdgeInsets.only(bottom: 15),
child: Row(
children: [
SizedBox(
width: 70,
child: AspectRatio(
aspectRatio: 0.88,
child: Container(
decoration: BoxDecoration(
color: Color(0xFFF5F6F9),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
'assets/note2.png',
),
),
),
),
SizedBox(width: 20),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Paramètre: ${mesures![index].param_name}",
style: TextStyle(
color: Colors.black, fontSize: 16),
maxLines: 2,
),
SizedBox(height: 10),
Text.rich(
TextSpan(
text:
"Description: ${mesures![index].description}",
style: TextStyle(
fontWeight: FontWeight.w600,
color: kPrimaryColor),
),
),
],
),
],
),
),
);
},
),
)
],
),
),
);
}
Can anyone help me out with it? thanks in advance!

How to fix a non-null String must be provided to a Text widget

this is part of my code, I keep getting a non-null String must be provided to a Text widget.
Still new to flutter, so I'm not sure on how to fix this. I tried putting the ??"" on child: Text(myQuiz[0][i.toString()] but then it gave me an error on The method '[]' was called on null.
Receiver: null
Tried calling:
Widget optionButton(String k) {
return Padding(
padding: EdgeInsets.only(
top: 10
),
child: MaterialButton(
onPressed: () => checkAns(k),
child: Text(
myQuiz[1][i.toString()][k],
style: TextStyle(
color: Colors.black,
fontFamily: "Open Sans",
fontSize: 16.0,
),
maxLines: 1,
),
color: buttonColor[k],
minWidth: 200.0,
height: 45.0,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Color(0xffb0dab9))),
),
);
}
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]);
return WillPopScope(
onWillPop: () {
return showDialog(
context: context,
builder: (context) => AlertDialog(
content: Text("You must finish this quiz :)"),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
'Ok',
),
)
],
));
},
child: Scaffold(
appBar: AppBar(title: Text('Quiz'),backgroundColor: Color(0xffb0dab9)),
backgroundColor: Colors.yellow[100],
body: Container(
padding: EdgeInsets.all(50),
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(20),
alignment: Alignment.center,
child: Text(myQuiz[0][i.toString()],
style: TextStyle(fontSize: 20.0, color: Colors.black),
),
),
AbsorbPointer(
absorbing: disableAnswer,
child: Container(
padding: EdgeInsets.only(top: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
optionButton('a'),
optionButton('b'),
optionButton('c'),
optionButton('d'),
],
),
),
),
Container(
padding: EdgeInsets.only(top: 30),
alignment: Alignment.topCenter,
child: Center(
child: Text(
showTimer ,
style: TextStyle(
fontSize: 20.0,
),
),
),
),
],
),
),
),
)
);
}
}
It is because a null value is being provide to your Text widget
From your code.. one or more of the following is null and not a string
myQuiz[1][i.toString()][k]
showTimer
Try
...
#override
Widget build(BuildContext context) {
print(myQuiz[1][i.toString()][k]);
print(showTimer);
to find out which is the null value
Try this.
Text(
myQuiz[1]?[i?.toString()]?[k] ?? "Default Value",
style: TextStyle(
color: Colors.black,
fontFamily: "Open Sans",
fontSize: 16.0,
),
maxLines: 1,
),
Thanks for helping, I have found the answer, it was in the getRandom, as the json does not have a 0, so when the quiz runs and hit 0, it causes the error

Modal Bottom Sheet hidden by keyboard in TabBarView

I am having an issue where the keyboard covers and hides the bottom sheet.
I tried a number of solutions but nothing seems to work. I am not too sure what is causing the problem. My guess is that it has something to do with either nested Scaffold and/or using bottom sheet in TabBarView.
Any help would be greatly appreciated.
I tried to include as much detail as possible. If you need anything else, please let me know.
Code below:
DetailsPage.dart
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
centerTitle: true,
title: UtilWidget.getLogo(),
bottom: TabBar(
labelColor: Colors.deepPurpleAccent,
unselectedLabelColor: Colors.white,
indicatorSize: TabBarIndicatorSize.label,
indicator: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10)),
color: Colors.white),
tabs: [
UtilWidget.addTab('Details'),
UtilWidget.addTab('Procedures'),
],
),
),
body: TabBarView(
children: <Widget>[
EditServiceFragment(contractorServiceId: widget.contractorServiceId),
ServiceProceduresFragment(contractorServiceId: widget.contractorServiceId)
],
),
)
);
}
ServiceProceduresFragment.dart
#override
Widget build(BuildContext context) {
return Scaffold(
primary: false,
resizeToAvoidBottomInset: true,
key: _scaffoldKey,
body: _buildPage(),
floatingActionButton: new FloatingActionButton.extended(
onPressed: () {
_addProcedureBottomSheet(context);
},
label: Text('Add Procedure'),
icon: new Icon(Icons.add),
),
);
}
Widget _buildPage() {
return FutureBuilder(
future: _loadedContractorService,
builder: (BuildContext context, AsyncSnapshot<ContractorService> serviceRes) {
if(serviceRes.hasError) {
print('Error while loading Asset - EditService');
print(serviceRes.error);
return UtilWidget.pageLoadError(
"SERVICE PROCEDURES",
"An Error has occurred",
"Got an error getting Contractor Service from the API."
);
}
if (serviceRes.connectionState == ConnectionState.waiting)
return UtilWidget.progressIndicator();
ContractorService loadedService = serviceRes.data;
List<Procedure> procedures = loadedService.procedures;
if(procedures.length == 0)
return UtilWidget.emptyListView('SERVICE PROCEDURES', 'No procedures were found. Add one.');
return SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
itemCount: procedures.length + 1,
itemBuilder: (context, index) {
if(index == 0){
return UtilWidget.pageHeader('SERVICE PROCEDURES');
}
int listIndex = index - 1;
Procedure procedure = procedures[listIndex];
return Card(
elevation: 2,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
margin: EdgeInsets.only(top: 10, bottom: 10, left: 20, right: 20),
child: Theme(
data: ThemeData().copyWith(
dividerColor: Colors.transparent,
accentColor: Colors.deepPurpleAccent
),
child: ExpansionTile(
title: ListTile(
title: Text(
procedure.name,
style: TextStyle(fontWeight: FontWeight.bold)
),
subtitle: Text(
'Requirements: ' +
procedure.requirements.length.toString()
),
),
childrenPadding: EdgeInsets.only(left: 20, right: 20),
children: [
UtilWidget.addRowWithText('Notes', FontWeight.bold),
UtilWidget.addRowWithText(procedure.notes, FontWeight.normal),
_deleteProcedureBtn(procedure.id),
Padding(
padding: const EdgeInsets.only(top: 10),
child: UtilWidget.addRowWithText('Requirements', FontWeight.bold),
),
for(var req in procedure.requirements)
UtilWidget.addRowWithText(req.name, FontWeight.normal)
,
_addRequirementBtn(procedure.id)
]
)
)
);
}
)
);
}
);
}
void _addProcedureBottomSheet(BuildContext context) {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: SingleChildScrollView(
padding: EdgeInsets.only(
top: 10, left:15, right:15,
bottom: MediaQuery.of(context).viewInsets.bottom
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Center(
child: Text(
'Add Procedure to Service',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18
),
),
),
_addProcedureForm()
],
),
)
);
}
);
}
Form _addProcedureForm() {
return Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
validator: (value) {
if(value.isEmpty) {
return 'Service name is required.';
}
return null;
},
controller: _name,
decoration: InputDecoration(
labelText: 'Name',
hintText: "Specific/applicable procedure",
icon: Icon(Icons.edit, color: Colors.deepPurple)
)
),
TextFormField(
validator: (value) {
if(value.isEmpty) {
return 'Service description is required.';
}
return null;
},
maxLines: null,
keyboardType: TextInputType.multiline,
controller: _notes,
decoration: InputDecoration(
labelText: 'Description',
hintText: "Applicable procedure description.",
icon: Icon(Icons.notes, color: Colors.deepPurple)
)
),
Container(
margin: const EdgeInsets.only(top: 20.0, bottom: 10),
child: SizedBox(
width: double.maxFinite,
child: RaisedButton(
color: Colors.deepPurple,
textColor: Colors.white,
padding: EdgeInsets.all(5),
child: Text('Save Procedure',
style: TextStyle(fontSize: 15)
),
onPressed: () {
if(_formKey.currentState.validate()) {
_submitProcedureForm();
}
},
),
),
)
],
),
);
}
Widget _addRequirementBtn(int procedureId) {
return Padding(
padding: const EdgeInsets.only(top: 10.0, bottom: 10),
child: RaisedButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
color: Colors.deepPurple,
textColor: Colors.white,
child: Text('Add Requirement',
style: TextStyle(fontSize: 14)
),
onPressed: () {
_addProcedureRequirementBottomSheet(procedureId, context);
}
)
);
}
Outputs
You can check the value of MediaQuery.of(context).viewInsets.bottom to know whether the keyboard is active and put some space to the bottom of the modal.
Also, you can use AnimatedPadding to make it look smooth.
void _addProcedureBottomSheet(BuildContext context) {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (BuildContext context) {
var keyboardHeight = MediaQuery.of(context).viewInsets.bottom ?? 0.0;
return AnimatedPadding(
padding: EdgeInsets.only(bottom: keyboardHeight),
duration: Duration(milliseconds: 300),
child: SafeArea(
bottom: keyboardHeight <= 0.0,
child: SingleChildScrollView(
padding: EdgeInsets.only(
top: 10,
left: 15,
right: 15,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Center(
child: Text(
'Add Procedure to Service',
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
),
),
_addProcedureForm()
],
),
),
),
);
},
);
}
Thanks to Stewie, I realized that MediaQuery.of(context).viewInsets.bottom wasn't registering the appearance of the keyboard.
I was able to solve the issue by passing in the BuildContext from the page with DefaultTabController to the TabView page. Using this BuildContext resolved the issue.
Code below:
ContractorServiceDetailsPage.dart
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
centerTitle: true,
title: UtilWidget.getLogo(),
bottom: TabBar(
labelColor: Colors.deepPurpleAccent,
unselectedLabelColor: Colors.white,
indicatorSize: TabBarIndicatorSize.label,
indicator: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10)),
color: Colors.white),
tabs: [
UtilWidget.addTab('Details'),
UtilWidget.addTab('Procedures'),
],
),
),
body: TabBarView(
children: <Widget>[
EditServiceFragment(contractorServiceId: widget.contractorServiceId),
ServiceProceduresFragment(
baseContext: context,
contractorServiceId: widget.contractorServiceId
)
],
),
)
);
}
ServiceProceduresFragment.dart
class ServiceProceduresFragment extends StatefulWidget {
final BuildContext baseContext;
final int contractorServiceId;
const ServiceProceduresFragment({
Key key,
this.contractorServiceId,
this.baseContext}) : super(key: key);
#override
State<StatefulWidget> createState() {
return _ServiceProceduresState();
}
}
class _ServiceProceduresState extends State<ServiceProceduresFragment> {
...
#override
Widget build(BuildContext context) {
return Scaffold(
primary: false,
resizeToAvoidBottomPadding: false,
key: _scaffoldKey,
body: _buildPage(),
floatingActionButton: new FloatingActionButton.extended(
onPressed: () {
_addProcedureBottomSheet(widget.baseContext);
},
label: Text('Add Procedure'),
icon: new Icon(Icons.add),
),
);
}
}
Did you try to wrap your SafeArea widget with Padding and adding
padding like :
=> ShowBottomSheet.instance.showBottomSheet(
isScrollControlled: true,
context: context,
widget: Padding(
padding: MediaQuery.of(context).viewInsets,
child: Container(
height: MediaQuery.of(context).size.height * 0.60,
child: DefaultTabController(
length: 2,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: MySize.size12),
child: Column(children: <Widget>[
const TabsOfTabbar(),
....... );

Problem with List builder repeat the data when adding or removing item in the list

I'm new to flutter. When I adding new item or removing an item from the list, the list builder does update the list, but the problem is that the list builder also displaying the previous item list and showing new updated item list. So what I want to do is keeping the new updated item list instead of old item list.
class AlarmPage extends StatefulWidget {
final String title;
AlarmPage({Key key, this.title}) : super(key: key);
#override
_AlarmPageState createState() => _AlarmPageState();
}
class _AlarmPageState extends State<AlarmPage> {
String alarmName;
// Test Function
void _addAlarm() {
setState(() {
Navigator.push(
context, MaterialPageRoute(builder: (context) => AddAlarm()));
});
}
#override
void initState() {
super.initState();
Provider.of<AlarmsProvider>(context, listen: false).getLocalStorage();
}
#override
Widget build(BuildContext context) {
List<Widget> allWidgetsAlarms = List<Widget>();
return Consumer<AlarmsProvider>(builder: (context, alarmProviderItem, _) {
List<String> localAlarms = alarmProviderItem.alarms;
if (localAlarms != null) {
localAlarms.forEach((item) {
allWidgetsAlarms.add(
Stack(
children: <Widget>[
InkWell(
child: Container(
color: Color(0xff212121),
padding: EdgeInsets.all(10),
child: Column(
children: <Widget>[
// Alarm Name & Title
Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: 2),
)),
child: Row(
children: <Widget>[
Icon(Icons.alarm, color: Colors.yellow),
SizedBox(width: 20.0),
Text('$item',
style: TextStyle(
color: Color(0xffC1C1C1),
fontSize: 15.0,
fontWeight: FontWeight.w900)),
SizedBox(height: 5),
],
),
),
SizedBox(height: 10),
// Alarm Time & Toggle Switch
Container(
child: Row(
children: <Widget>[
Text(
'Time',
style: TextStyle(
fontSize: 30, color: Colors.white),
),
SizedBox(width: 20),
Text(
'AM / PM',
style: TextStyle(
fontSize: 20, color: Color(0xffB5B5B5)),
),
SizedBox(width: 150),
Icon(Icons.switch_camera, color: Colors.yellow),
],
),
),
// Alarm Repeat
Container(
child: Row(children: <Widget>[
Text(
'Repeat',
style: TextStyle(
fontSize: 11, color: Color(0xff616161)),
),
Container(
child: DaySelector(
value: null,
onChange: (value) {},
color: Colors.yellow[400],
mode: DaySelector.modeFull,
),
),
]),
),
],
),
),
onLongPress: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddAlarm(item: item)));
},
),
SizedBox(height: 180),
],
),
);
print(item);
});
}
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
title: Text('Azy Alarm'),
centerTitle: true,
),
body: Container(
decoration: BoxDecoration(
image: const DecorationImage(
fit: BoxFit.cover,
image: AssetImage('assets/images/background_image(dark).png')),
),
// child: ListView(children: allWidgetsAlarms),
child: ListView.builder(
itemCount: allWidgetsAlarms.length,
padding: const EdgeInsets.all(8.0),
itemBuilder: (BuildContext context, int index) {
return allWidgetsAlarms[index];
}),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
backgroundColor: Colors.blue,
elevation: 0,
onPressed: _addAlarm,
),
);
});
}
}
So I think your issue is this line: allWidgetsAlarms.add( You construct allWidgetsAlarms in your builder, but the builder is not called again every time you Consumer rebuilds, hence it is just appending the new contents to the end of the list. To fix this, keep your original initialization of allWidgetsAlarms just at the top of the builder in your Consumer, add the following line:
allWidgetsAlarms = List<Widget>();
This will resert allWidgetsAlarms. Hope it helps!