Flutter ListView can't tap items - flutter

I'm using flutter_maps map and overlaying a custom search bar with drop down menu. When user searches, locations appear and should be clickable. Using the below code, the UI appears, but clicks aren't possible and nothing happens. I've also noticed the list view can't be scrolled either, can anyone see what the issue is?
List<Widget> _locations = [];
Future<void> searchLocations(String input) async {
final database =
await $FloorLocalDatabase.databaseBuilder('local_database.db').build();
final locationsDao = database.locationDao;
locationsDao.searchLocations(input).then((value) => {
setState(() {
_locations = [];
value.forEach((element) {
_locations.add(locationItem(element));
});
})
});
}
#override
Widget build(BuildContext context) {
return FlutterMap(
options: MapOptions(
center: LatLng(51.5072, -0.1276),
zoom: zoom,
interactiveFlags: InteractiveFlag.pinchZoom | InteractiveFlag.drag,
),
children: [
TileLayer(
urlTemplate: "https://tile.openstreetmap.org/{z}/{x}/{y}.png"),
MarkerLayer(markers: _markers),
Padding(
padding:
const EdgeInsets.only(top: 16.0, left: 16.0, right: 16.0),
child: SizedBox(
height: 56.0,
child: Card(
shape: roundedCorner32,
elevation: 6.0,
child: Wrap(children: [
Column(children: [
TextField(
cursorColor: Theme.of(context).colorScheme.secondary,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(left: 16.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0),
borderSide: const BorderSide(
width: 0,
style: BorderStyle.none,
)),
filled: true,
hintStyle: TextStyle(color: Colors.grey[800]),
hintText: search,
fillColor: Colors.white),
onChanged: (value) {
searchLocations(value);
},
),
if (_locations.isNotEmpty) ...[
Card(
color: Theme.of(context).colorScheme.primary,
shape: roundedCorner16,
elevation: 6.0,
child: Wrap(children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.all(8.0),
color: Theme.of(context).colorScheme.primary,
child: ListView.separated(
shrinkWrap: true,
itemCount: _locations.length,
itemBuilder:
(BuildContext context, int index) {
return GestureDetector(
onTap: () {
print("XXXXXXXXXXX");
},
child: _locations[index],
);
}, separatorBuilder: (BuildContext context, int index) {
return const SizedBox(height: 8.0);
},),
),
),
]),
)
]
]),
]),
),
)),
]);
}
Widget locationItem(Location location) {
return AutoSizeText(buildFullLocation(location), maxLines: 1);
}

How about try wrap the TextFiled widget in an Inkwell or GestureDetector widget?
GestureDetector(
onTap: (){},
child: TextField()),

Related

Bottom overflowed by 11 pixels

I'm having bottom overflowed by pixels flutter when showing keyboard, i tried SingleChildSCrollView and still couldn't find the solution for it. my aim to make the Get.defaultDialog scrollable.
here my code :
class AddCard extends StatelessWidget {
final homeCtrl = Get.find<HomeController>();
AddCard({super.key});
#override
Widget build(BuildContext context) {
final icons = getIcons();
var squareWidth = Get.width - 12.0.wp;
return Container(
width: squareWidth / 2,
height: squareWidth / 2,
margin: EdgeInsets.all(3.0.wp),
child: InkWell(
onTap: () async {
await Get.defaultDialog(
titlePadding: EdgeInsets.symmetric(vertical: 5.0.wp),
radius: 5,
title: 'Task Type',
content: Form(
key: homeCtrl.formKey,
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 3.0.wp),
child: TextFormField(
controller: homeCtrl.editCtrl,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'title',
),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return 'Please enter your task title';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 5.0.wp),
child: Wrap(
spacing: 2.0.wp,
children: icons
.map((e) => Obx(() {
final index = icons.indexOf(e);
return ChoiceChip(
selectedColor: Colors.grey[200],
pressElevation: 0,
backgroundColor: Colors.white,
label: e,
selected: homeCtrl.chipIndex.value == index,
onSelected: (bool selected) {
homeCtrl.chipIndex.value =
selected ? index : 0;
},
);
}))
.toList(),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
minimumSize: const Size(150, 40),
),
onPressed: () {
if (homeCtrl.formKey.currentState!.validate()) {
int icon =
icons[homeCtrl.chipIndex.value].icon!.codePoint;
String color =
icons[homeCtrl.chipIndex.value].color!.toHex();
var task = Task(
title: homeCtrl.editCtrl.text,
icon: icon,
color: color,
);
}
},
child: const Text("Confirm"),
),
],
),
));
},
child: DottedBorder(
color: Colors.grey[400]!,
dashPattern: const [8, 4],
child: Center(
child: Icon(
Icons.add,
size: 10.0.wp,
color: Colors.grey,
),
)),
),
);
}
}
The widget that makes the error is the Get.defaultDialog().
There are two ways:
You can use the resizeToAvoidBottomInset property on the Scaffold widget.
You can use ListView instead Column:
onTap: () async {
await Get.defaultDialog(
radius: 5,
titlePadding: EdgeInsets.symmetric(vertical: 5.0),
title: Text('Task Type'),
content: SizedBox(
height: 500,//your height
width: 300, //your width
child:
Form(
child: ListView(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 3.0),
child: TextFormField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'title',
),
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 5.0),
child: Wrap(
spacing: 2.0,
children: List.generate(//replace with your content
100,
(index) => Container(
height: 20,
width: 50,
padding: EdgeInsets.all(20),
color: Colors.red,
))),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
minimumSize: const Size(150, 40),
),
onPressed: () {},
child: const Text("Confirm"),
),
],
),
),
),
),
);
It`s important to give your dialog a fixed height and width, in this defined area it's possible to make a scrollable widget work.
If your aim is to make the dialog scrollable, Use ListView with defined height.
Further for your SizedBox to work as expected in case of any overplexes use the Flexible widget
Try the code structure:
GetDialog
|_Flexible
|_SizedBox 👈Define proper height and width here
|_ListView
I can't really understand your question well because you only posted part of the codes, but try wrapping your Scaffold body with SingleChildScrollView.
maybe you're using the SingleChildScrollView at a wrong place.

Dynamic listview in flutter

I'm new to Flutter, but I'm trying to make an app with a ListView. The ListView is a list of exercises, within each exercise the number of sets can be added. The problem comes when i press the button add exercise. The above exercise with sets is just copied. I would like a new exercise tab with 0 sets. Below the code can be found.
Here is a picture of the list.
final decoratedField = InputDecoration(
filled: false,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
hintText: "null",
);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: [
titleSection,
// ignore: unnecessary_new
new TextField(
controller: eCtrl,
onSubmitted: (text) {
litems.add(text);
eCtrl.clear();
setState(() {});
},
),
Expanded(
// ignore: unnecessary_new
child: new ListView.builder(
itemCount: litems.length,
itemBuilder: (BuildContext ctxt, int Index) {
return Card(
child: Padding(
padding: EdgeInsets.all(10),
child: ExpansionTile(
initiallyExpanded: true,
title: Text(
litems[Index],
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
subtitle: Row(
children: [
Expanded(child: Text(" ")),
//Expanded(child: Text("data")),
//Expanded(child: Text("data")),
//Expanded(child: Text("data")),
],
),
// ignore: sort_child_properties_last
children: <Widget>[
ListView.builder(
shrinkWrap: true,
itemCount: sets.length,
itemBuilder:
(BuildContext context, int Index1) {
return Dismissible(
key: UniqueKey(),
// only allows the user swipe from right to left
direction:
DismissDirection.endToStart,
// Remove this product from the list
// In production enviroment, you may want to send some request to delete it on server side
onDismissed: (_) {
setState(() {
sets.removeAt(Index1);
});
},
// ignore: sort_child_properties_last
child: Card(
elevation: 0,
child: Padding(
padding: EdgeInsets.all(1),
child: ListTile(
title: Text(
" ",
style: const TextStyle(
fontSize: 10,
fontWeight:
FontWeight.bold,
),
),
subtitle: Row(
children: [
Expanded(
child: Text(" "),
),
Expanded(
child: TextField(
decoration:
decoratedField,
),
),
Expanded(
child: TextField(
decoration:
decoratedField,
),
),
Expanded(
child: TextField(
decoration:
decoratedField,
),
),
],
),
))),
background: Container(
color: Colors.red,
margin:
const EdgeInsets.symmetric(
horizontal: 15,
),
alignment: Alignment.centerRight,
child: const Text(
"Delete",
style: TextStyle(
color: Colors.white,
),
)));
}),
Padding(
padding: EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () {
sets.add('sets-test');
setState(() {});
},
child: const Text('+ Add Set')),
),
const SizedBox(height: 5),
],
leading: IconButton(
icon: const Icon(
Icons.close,
color: Colors.red,
),
onPressed: () {
litems.removeAt(Index);
setState(() {});
},
),
)));
})),
ElevatedButton(
onPressed: () {
litems.add("new");
setState(() {});
},
child: const Text('Add Exercises')),
ElevatedButton(
onPressed: () {
createUser(user1, "5");
exercise.setExerciseTotals();
//saveExercise(exercise);
final workout = Workout([exercise, exercise1], "Det gik fint",
"10", 60, "type", "name", true, 0, 0, 0);
//workout.setWorkoutTotals();
saveWorkout(workout, userID);
},
child: const Text('pop')),
bottomSection,
],
),
));
}
You are not copy the item, you logic is that add new Item with null value, change decoratedField to this:
final decoratedField = InputDecoration(
filled: false,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
hintText: "0",
);

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();
},
),
),
),
);
}

passing data immediately without using setstate

Is there a way to pass data when from alert dialogue box to the same screen immediately without using setstate?
Widget setupShadeColorContainer(
List<ShadeColorDatabase> allShadeData, BuildContext context) {
return SizedBox(
height: 300.0, // Change as per your requirement
width: 300.0, // Change as per your requirement
child: GridView.builder(
shrinkWrap: true,
itemCount: allShadeData.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4, crossAxisSpacing: 10, mainAxisSpacing: 10),
itemBuilder: (ctx, i) {
return GestureDetector(
onTap: () {
rPassedChooseColor = allShadeData[i].rValue;
gPassedChooseColor = allShadeData[i].gValue;
bPassedChooseColor = allShadeData[i].bValue;
setState(() {
Navigator.pop(context, [
rPassedChooseColor,
gPassedChooseColor,
bPassedChooseColor
]);
});
},
child: Container(
child: Stack(
children: [
Container(
color: Color.fromRGBO(
allShadeData[i].rValue!.toInt(),
allShadeData[i].gValue!.toInt(),
allShadeData[i].bValue!.toInt(),
1),
),
Padding(
padding: const EdgeInsets.only(top: 45, left: 5),
child: Text("${allShadeData[i].colorCode}"),
)
],
),
),
);
}),
);
}
showAllColors(
List<ShadeColorDatabase> shadeData, BuildContext context) async {
final size = MediaQuery.of(context).size;
final GlobalKey<FormState> _form = GlobalKey<FormState>();
TextEditingController searchController = TextEditingController();
showDialog(
barrierDismissible: true,
context: context,
builder: (ctx) {
return WillPopScope(
onWillPop: () async => false,
child: AlertDialog(
title: Center(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Fashion's Color",
style: TextStyle(
color: ChooseColor(0).appBarColor1, fontSize: 14),
),
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: const Icon(Icons.clear))
],
),
Form(
key: _form,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
border: const OutlineInputBorder(
borderSide: BorderSide.none,
),
contentPadding: EdgeInsets.symmetric(
vertical: size.height * 0.001,
horizontal: size.width * 0.030),
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.red, width: 1),
borderRadius: BorderRadius.circular(5)),
// labelText: 'Phone Number',
fillColor: const Color(0xffF6F9FA),
filled: true,
hintText: 'Search Color',
prefixIcon: const Icon(Icons.search),
hintStyle: TextStyle(
fontSize: size.height * 0.012 +
size.width * 0.012,
color: Colors.black26),
),
controller: searchController,
),
SizedBox(height: size.height * 0.035),
],
)),
],
),
),
content: setupShadeColorContainer(shadeData, context),
),
);
});
This is my dialogue box this dilogue box open over a screen and i want to pass data from this dilogue box to the same page immediately without using setstate is there any way i can achieve that?. Thanks
showDialog() can return future, and you can return data(myData) on closing dialog using
Navigator.of(context).pop(myData);
showAllColors() async {
final data = await showDialog(context: context, builder: (c){
// on closing dialog
Navigator.of(context).pop(passData);
return data;
}
When you use showAllColors try putting await on async method and also make sure to handle null data.

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.