Update item widget from local database list - flutter

I'm using a ready-made local database in my application and the problem is that I can't update one item from the list. If I add a chapter to favorites, then the button's state is updated only after the page is reopened. Likewise, the favorites list is updated only when the page is reopened. Right now when I add/remove favorites, I dynamically load the entire list so that it updates the values, but I only need to update one item, how can I do this using a provider? I didn’t give code examples, because I want to understand exactly the logic of actions
UPD:
My code:
#override
Widget build(BuildContext context) {
return FutureBuilder<List>(
future: _databaseQuery.getAllChapters(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
return snapshot.connectionState == ConnectionState.done &&
snapshot.hasData
? CupertinoScrollbar(
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return MainChapterItem(
item: snapshot.data![index],
);
},
),
)
: const Center(
child: CircularProgressIndicator.adaptive(),
);
},
);
}
Item:
final MainChapterItemModel item;
#override
Widget build(BuildContext context) {
return Material(
child: InkWell(
child: Container(
padding: const EdgeInsets.all(8),
child: Row(
children: [
IconButton(
icon: item.favoriteState == 0
? const Icon(CupertinoIcons.bookmark)
: const Icon(CupertinoIcons.bookmark_fill),
splashRadius: 22,
splashColor: const Color(0xff81b9b0),
onPressed: () {
context.read<BookmarkButtonState>().addRemoveChapterBookmark(
item.favoriteState == 0 ? 1 : 0, item.id);
},
),
const SizedBox(
width: 8,
),
Flexible(
child: ListTile(
contentPadding: EdgeInsets.zero,
title: Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Text(
item.chapterNumber,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
subtitle: Html(
data: item.chapterTitle,
style: {
'#': Style(
fontSize: const FontSize(17),
padding: EdgeInsets.zero,
margin: EdgeInsets.zero,
),
'small': Style(
fontSize: const FontSize(8),
),
'a': Style(
fontSize: const FontSize(14),
color: Colors.blue,
),
},
),
),
),
],
),
),
onTap: () {},
),
);
}
The problem is that when I add to favorites or delete, the button state is not updated. And in the favorites list, the item is not deleted on click, but it disappears after the page is reopened:
IconButton(
icon: item.favoriteState == 0
? const Icon(CupertinoIcons.bookmark)
: const Icon(CupertinoIcons.bookmark_fill),
splashRadius: 22,
splashColor: const Color(0xff81b9b0),
onPressed: () {
context.read<BookmarkButtonState>().addRemoveChapterBookmark(
item.favoriteState == 0 ? 1 : 0, item.id);
},
),
Provider code:
final DatabaseQuery _databaseQuery = DatabaseQuery();
DatabaseQuery get getDatabaseQuery => _databaseQuery;
addRemoveChapterBookmark(int state, int chapterId) {
_databaseQuery.addRemoveFavoriteChapter(state, chapterId);
notifyListeners();

I solved the problem by signing all lists to listen to databaseQuery in the provider:
future: context.watch<BookmarkButtonState>().getDatabaseQuery.getAllChapters(),

Related

List on HomeScreen not updating after editing an item in TaskScreenin Flutter

I am trying to do a todoapp with Provider but it is not working as expected. In my HomeScreen, I have a list of tasks, which is being stored in the provider. To edit a task, I go to another screen, TaskScreen, where I submit a form and, ideally, it should update the list, but it does not. Actually it does, but only after a hot reload, it is not synchronized.
class Task extends StatelessWidget {
String title;
Task({super.key, required this.title});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => {
Navigator.of(context).pushNamed(
'/task',
arguments: TitleTask(title: title),
),
FocusManager.instance.primaryFocus?.unfocus(),
},
child: Dismissible(
key: Key(title),
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blue,
width: 1,
style: BorderStyle.solid,
),
borderRadius: BorderRadius.circular(10),
color: Colors.grey[300],
),
margin: const EdgeInsets.only(bottom: 8.0),
child: ListTile(
title: Text(
title,
style: const TextStyle(fontSize: 18),
),
trailing: Wrap(
spacing: 0,
children: <IconButton>[
IconButton(
padding: EdgeInsets.zero,
icon: const Icon(Icons.delete),
color: Colors.red,
onPressed: () => context.read<Tasks>().delete(title),
),
IconButton(
padding: EdgeInsets.zero,
icon: const Icon(Icons.check),
color: Colors.green,
onPressed: () => {},
)
],
),
),
),
onDismissed: (direction) => context.read<Tasks>().delete(title),
),
);
}
}
class Tasks with ChangeNotifier {
final List<Task> _tasks = [];
List get tasks => _tasks;
void add(String title) {
_tasks.add(Task(title: title));
notifyListeners();
}
void delete(String title) {
_tasks.removeWhere((element) => element.title == title);
notifyListeners();
}
void edit(String? taskTitle, String newTaskTitle) {
_tasks[_tasks.indexWhere((element) => element.title == taskTitle)].title =
newTaskTitle;
notifyListeners();
}
}
I am building the list of tasks like this:
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: context.watch<Tasks>().tasks.length,
itemBuilder: (context, index) {
final item = context.watch<Tasks>().tasks[index];
return item;
},
Does anyone know what is happening? I fear it may be related to the provider not knowing that it needs to update, because it knows the value and it doesn't update.
To achieve exactly what you want you need to wrap your ListView with Consumer class instead of using watch inside of ListView.builder
Consumer<Tasks>(
builder: (_, data, __) => ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: data.tasks.length,
itemBuilder: (context, index) {
final item = data.tasks[index];
return item;
},)
)
Happy coding

Flutter > Unselect a RadioButton in a View.builder

I am not finding any answer for my question so I am hoping to find someone who can help.
I have a GridView with text buttons.
I can select the buttons, however I can't unselect any of them.
this is my code
#override
Widget build(BuildContext context) {
return TextButton(
onLongPress: () => showDialog<String>(
),
style: ButtonStyle(
side: MaterialStateProperty.all(BorderSide(
width: 5,
color: widget.isSelected ? Colors.black : Colors.white)),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))),
backgroundColor: MaterialStateProperty.all(widget.pickerColor),
elevation: MaterialStateProperty.all(10)),
onPressed: () {
widget.selectedCard(widget.index); //This selects the cards, how to unselect (if Statements?)
},
child: FittedBox(
fit: BoxFit.fitHeight,
child: Text(
widget.cardTitle,
style: TextStyle(
fontSize: 17,
color: useWhiteForeground(widget.pickerColor)
? const Color(0xffffffff)
: const Color(0xff000000),
),
),
),
);
}
}
This is the Grid
#override
Widget build(BuildContext context) {
return Consumer<MyCardData>(
builder: (context, cardData, child) {
return Padding(
padding: const EdgeInsets.all(10),
child: GridView.builder(
clipBehavior: Clip.none,
itemBuilder: (context, index) {
final card = cardData.cards[index];
return MyCard(
selectedCard,
index: index,
isSelected: _selectedCard == index,
cardTitle: card.name,
pickerColor: card.cardColor,
deleteCallback: () {
cardData.deleteCallback(card);
},
);
},
itemCount: cardData.cardCount,
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 150,
childAspectRatio: 2.5 / 1,
crossAxisSpacing: 0,
mainAxisSpacing: 0,
),
),
);
},
);
}
}
feel free to use my git to see the full code
get from version control
since you want to make a single selection, it will need a simple workaround.
int _selectedCard = -1;
selectedCard(index) {
// this condition is when user press the same button
// set the _selectedCard back into -1
if (_selectedCard == index) {
setState(() {
_selectedCard = -1;
});
} else{
setState(() {
_selectedCard = index;
});
}
}

How to show total item of the listview?

Please help me. I want to show total items of the list view in the card. Basically, first it will show all 3 category. If you click one of the category it will show all the list of item. So, the problem I want to solve is to show the total of item based on the category.
Coding below i tried using .length and List but it does not show the total of item I register.
class CaseListCategory extends StatefulWidget {
const CaseListCategory ({Key? key}) : super (key : key);
#override
_CaseListCategoryState createState() => _CaseListCategoryState();
}
class _CaseListCategoryState extends State<CaseListCategory> {
#override
Widget build(BuildContext context) {
final docCase = FirebaseFirestore.instance.collection('cases').doc();
List<CriticalCaseList> cases = [];
return Scaffold(
body: Container(
padding: EdgeInsets.all(10),
child: ListView(
children: <Widget>[
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => CriticalCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.red,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Container(
child: Column(
children: [
Text(
'CRITICAL',
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
Text(
"${cases.length}",
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
],
),
),
),
),
),
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ModerateCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.orange,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Column(
children: [
Text(
"MODERATE",
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
Text(
"${cases.length}",
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
],
),
),
),
),
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => LowCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.yellow,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Column(
children: [
Text(
'LOW',
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
Text(
"${cases.length}",
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
],
),
),
),
),
],),
)
);
}
}
Here are the coding of page after i click the card. it show all of item
Category page
List of item page
class CriticalCaseList extends StatefulWidget {
const CriticalCaseList ({Key? key}) : super (key : key);
#override
_CriticalCaseListState createState() => _CriticalCaseListState();
}
class _CriticalCaseListState extends State<CriticalCaseList> {
User? user = FirebaseAuth.instance.currentUser;
final CollectionReference _cases = FirebaseFirestore.instance.collection('cases');
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Critical Case"),
backgroundColor: Colors. redAccent,
centerTitle: true,
leading: IconButton(
icon: const Icon(Icons.arrow_back),
color: Colors.white,
iconSize: 30,
onPressed: () => Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => const VolunteerPage())),
),
),
// Using StreamBuilder to display all products from Firestore in real-time
body: StreamBuilder(
stream: _cases.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> streamSnapshot) {
if (streamSnapshot.hasData) {
return ListView.builder(
itemCount: streamSnapshot.data!.docs.length,
itemBuilder: (context, index) {
final DocumentSnapshot documentSnapshot = streamSnapshot.data!.docs[index];
if(documentSnapshot['priority'] == "Critical" && documentSnapshot['status'] == "Waiting for rescue"){
return Card(
child: ListTile(
title: Text(documentSnapshot['name']),
subtitle: Text(documentSnapshot['priority'].toString()),
trailing: Icon(Icons.arrow_forward),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => CaseListView(cid: documentSnapshot['cid']))
);
},
)
);
}
return Card();
},
);
}
return const Center(
child: CircularProgressIndicator(),
);
},
),
);
}
}
Problems
There are two problems with the code.
In CriticalCaseList, documentSnapshot is a snapshot and not the document data itself, so you need to access data from it after calling .data() on the documentSnapshot.
In CaseListCategory, cases.length is not working because there is no part of the code that is filling up cases from Firestore.
It will be improper to use cases.length because cases will contain the total of all the cases (irrespective of their categories). But you want the individual totals of critical, moderate, or low categories.
Solution
So in CriticalCaseList, change the following line
final DocumentSnapshot documentSnapshot = streamSnapshot.data!.docs[index];
to
final DocumentSnapshot documentSnapshot = streamSnapshot.data!.docs[index].data();
(notice .data() appended at the end)
Given that you want to display the total number of cases in each category, what you can do is keep track of each categories total.
So you can have variables for each of them. Then initialize their values in initState. And still in initState, you can use .snapshots().listen() on the collection reference of cases. This way, every time cases are added or removed, The CaseListCategory widget will update the total of each case and display the current total. Also, remember to cancel the StreamSubscription in dispose().
Finally, in the parts of the code where you display the totals, instead of using cases.length, you use the total of the given category. The following should work:
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'critical_case_list.dart';
import 'moderate_case_list.dart';
import 'low_case_list.dart';
class CaseListCategory extends StatefulWidget {
const CaseListCategory({Key? key}) : super(key: key);
#override
_CaseListCategoryState createState() => _CaseListCategoryState();
}
class _CaseListCategoryState extends State<CaseListCategory> {
double _criticalCases = 0, _moderateCases = 0, _lowCases = 0;
late StreamSubscription _listener;
#override
void initState() {
super.initState();
_listener = FirebaseFirestore.instance
.collection('cases')
.snapshots()
.listen((snap) {
final cases = snap.docs.map((doc) => doc.data());
_criticalCases = 0;
_moderateCases = 0;
_lowCases = 0;
for (var caseData in cases) {
if (caseData['priority'] == 'Critical') _criticalCases++;
if (caseData['moderate'] == 'Moderate') _moderateCases++;
if (caseData['low'] == 'Low') _lowCases++;
}
setState(() {});
});
}
#override
void dispose() {
_listener.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.all(10),
child: ListView(
children: <Widget>[
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => CriticalCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.red,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Container(
child: Column(
children: [
Text(
'CRITICAL',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
Text(
'$_criticalCases',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
],
),
),
),
),
),
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ModerateCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.orange,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Column(
children: [
Text(
"MODERATE",
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
Text(
'$_moderateCases',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
],
),
),
),
),
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => LowCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.yellow,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Column(
children: [
Text(
'LOW',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
Text(
'$_lowCases',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
],
),
),
),
),
],
),
));
}
}
Better solution
Your current setup is expensive. Or rather, it will be costly as your app grows or scales. Firebase charges you for every document read. That said, every time CaseListCategory is loaded, Firestore will read all the documents in the cases collection. And every time any document in that collection is created, updated, or deleted, Firestore will fetch all of them again (to update the totals).
A common pattern to reduce such cost is to have a counters collection. Inside it, you will have documents for each category that will maybe have a total property, holding the current total of a given category.
Then you increment or decrement the current count of a given category when a case is created or deleted. A better place to run this logic is in Cloud Functions, where you are sure that the code would run. Updating the counts in clients is not recommended because the client's network might fail or also for security reasons.
So you could have the following code in cloud functions in index.js file.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.incrementCaseCount = functions.firestore
.document('/cases/{caseId}')
.onCreate(async (snap, _) => {
const category = snap.data()['priority'].toLowerCase();
await db
.doc(`/counters/${category}Cases`)
.set({ total: admin.firestore.FieldValue.increment(1) }, { merge: true })
.catch((error) => console.error(error));
});
exports.decrementCaseCount = functions.firestore
.document('/cases/{caseId}')
.onDelete(async (snap, _) => {
const category = snap.data()['priority'].toLowerCase();
await db
.doc(`/counters/${category}Cases`)
.set({ total: admin.firestore.FieldValue.increment(-1) }, { merge: true })
.catch((error) => console.error(error));
});
And then in flutter, in the initState of CaseListCategory, instead of listening to snapshots of the entire cases collection, you can listen to snapshots of only the counters collection. counters collection would have a small number of documents, so it is cheaper to read from them than to read all the documents in the cases collection.
So you can have the following in initState.
_listener = FirebaseFirestore.instance
.collection('counters')
.snapshots()
.listen((snap) {
for (var doc in snap.docs) {
if (doc.id == 'criticalCases') _criticalCases = doc.data()['total'];
if (doc.id == 'moderateCases') _moderateCases = doc.data()['total'];
if (doc.id == 'lowCases') _lowCases = doc.data()['total'];
}
setState(() {});
});

Type 'Future<dynamic>' is not subtype of type 'Widget'

I am showing markers from API on google maps. Here is my build method. When the program reaches the _widgetbuilder() method, it throws the specific error of type Future is not a subtype of the widget. If someone could please help to solve the problem and also tell me that what exactly this error means.....
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: FutureBuilder<List<MarkersOnMap>>(
future: future,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData)
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
if (snapshot.hasData && snapshot.data.isEmpty) {
return Center(
child: Container(
child: Column(
children: [
Text(
'No Properties Added Yet\nPlease Add Some!',
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
ElevatedButton.icon(
onPressed: () {
Navigator.push(
context,
PageTransition(
duration: Duration(microseconds: 500),
type: PageTransitionType.fade,
child: AddNewEproperty(
createEproperty: widget.createEproperty),
),
);
},
label: Text('Add'),
icon: Icon(Icons.add),
),
],
),
),
);
} else
_widgetbuilder();
if (snapshot.hasData) {
return ListView.builder(
itemCount: allWidgets.length + 1,
shrinkWrap: true,
padding: EdgeInsets.only(top: 16),
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, i) {
return Stack(
children: <Widget>[
Container(),],);},);},},),);}
This is the _widgetbuilder() method. When it reaches this return _widgetbuilder, throws _typeerror.
_widgetbuilder() async {
allWidgets = [];
widget.markersonmap = await future;
widget.markersonmap.forEach(
(element) {
print(element);
allWidgets.add(
Container(
height: 25,
width: 50,
child: new DecoratedBox(
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
borderRadius: BorderRadius.circular(5.0),
color: Colors.black54),
child: Text(
element.ePropertiesCardsList.price.toString(),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
),
);
},
);
}
You are getting this error because your function _widgetbuilder returns Future<dynamic> because the function is async.
Widget _widgetbuilder(){
// code here
}
The function should be in this structure to return of type Widget. The code that needs to be async should either be taken out of build function or use .then pattern for async code instead of async await if you really need to.
This short 9 min video will help you understand async better in flutter.
In here now the type error is solved but after reading 'future.then..... it does not goto the future and fetch data but jumps to the next foreach line and then calls it as null.
_widgetbuilder() {
allWidgets = [];
// widget.markersonmap = await future;
future.then((value) {
widget.markersonmap = value;
});
widget.markersonmap.forEach(
(element) {
print(element);
allWidgets.add(
Container(
// other code
}

How to make just one ExpansionPanel, in an ExpansionPanelList different to the others? flutter

As the question suggests I have an ExpansionPanelList, one ExpansionPanel (the last one or the 7th one) should have 2 additional buttons, but how can I add them just in this one last panel & not in all the others as well?
This is the code of my whole Expansion panel, as Im not sure where you have to add the behaviour, but guessing in the body of the ExpansionPanel (close to line 40):
class ExpansionList extends StatefulWidget {
final Info info;
const ExpansionList({
Key key,
this.info,
}) : super(key: key);
#override
_ExpansionListState createState() => _ExpansionListState();
}
class _ExpansionListState extends State<ExpansionList> {
Widget _buildListPanel() {
return Container(
child: Theme(
data: Theme.of(context).copyWith(
cardColor: Color(0xffDDBEA9),
),
child: ExpansionPanelList(
dividerColor: Colors.transparent,
elevation: 0,
expansionCallback: (int index, bool isExpanded) {
setState(() {
infos[index].isExpanded = !isExpanded;
});
},
children: infos.map<ExpansionPanel>((Info info) {
return ExpansionPanel(
headerBuilder: (BuildContext context, bool isExpanded) {
return ListTile(
title: !isExpanded
? Text(
info.headerValue,
) //code if above statement is true
: Text(
info.headerValue,
textScaleFactor: 1.3,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
);
},
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
color: Color(0xffFFE8D6),
borderRadius: BorderRadius.circular(25)),
child: Column(
children: [
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: EdgeInsets.only(left: 40.0,),
itemCount: info.expandedValueData.length,
itemBuilder: (context, index) {
return CheckboxListTile(
title: Text(info.expandedValueData[index].title,
style: TextStyle(
decoration: info.expandedValueData[index]
.completed
? TextDecoration.lineThrough
: null)),
value: info.expandedValueData[index].completed,
onChanged: (value) {
setState(() {
// Here you toggle the checked item state
infos.firstWhere(
(currentInfo) => info == currentInfo)
..expandedValueData[index].completed =
value;
});
});
},
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
height: 20,
);
},
),
Row(children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.16),
Text("Abschnitt bis zum Neustart löschen"),
SizedBox(
width: MediaQuery.of(context).size.width * 0.11),
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
setState(() {
infos.removeWhere(
(currentInfo) => info == currentInfo);
});
},
)
]),
],
),
),
),
isExpanded: info.isExpanded);
}).toList(),
),
),
);
}
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
child: _buildListPanel(),
),
);
}
}
Thanks for suggestions!
Hi Just add a field (if you already do not have one) in the info object that will allow you to change the widget that is inflated based on that field.
For example
...
children: infos.map<ExpansionPanel>((Info info) {
return ExpansionPanel(
headerBuilder: (BuildContext context, bool isExpanded) {
return info.type == TYPE_A ? TypeAWidgetHeader(info) : TypeBWidgetHeader(info);
body: info.type == TYPE_A ? TypeAWidgetBody(info) : TypeBWidgetBody(info);
...