Range Error keeps appearing when dismissible widget is run - flutter

Here is my code
import 'package:flutter/material.dart';
void main() => runApp(TodoList());
class TodoList extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _TodoListState();
}
}
var TaskTextField;
List taskTextList = [];
var TaskIsImportant = false;
class _TodoListState extends State<TodoList> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
title: "To-Do List V2",
home: Scaffold(
appBar: AppBar(
title: Text("To-Do List V2"),
),
body: Flex(
direction: Axis.vertical,
children: <Widget>[
Flexible(
fit: FlexFit.tight,
child: Column(children: <Widget>[
Container(
child: TextField(
decoration: InputDecoration(
hintText: "Enter title of task to be added"),
onChanged: (taskTextField) {
setState(() {
TaskTextField = taskTextField;
print(TaskTextField);
});
},
),
margin: EdgeInsets.all(16.0),
),
CheckboxListTile(
title: Text("Important"),
activeColor: Colors.blue,
value: TaskIsImportant,
onChanged: (val) {
setState(() {
TaskIsImportant = !TaskIsImportant;
print(TaskIsImportant);
});
},
),
Text(
"Tip: Tap on your task to remove it",
style: TextStyle(fontSize: 15.0),
),
Container(
margin: EdgeInsetsDirectional.fromSTEB(117, 10, 117, 5),
child: Row(
children: <Widget>[
RaisedButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
if (TaskIsImportant) {
taskTextList.add("❗️$TaskTextField");
//taskTitleList.add(TaskDetailField);
} else {
taskTextList.add(TaskTextField);
//taskTitleList.add(TaskDetailField);
}
});
},
),
RaisedButton(
child: Icon(Icons.done_all),
onPressed: () {
setState(() {
taskTextList = [];
});
},
),
],
),
),
Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
var title = taskTextList[index];
padding:
EdgeInsets.all(16.0);
return Dismissible(
key: Key(title[index]),
onDismissed: (direction) {
setState(() {
taskTextList.remove(title);
});
},
child: ListTile(
title: Text(
title,
style: TextStyle(fontSize: 20.0),
),
),
);
},
itemCount: taskTextList.length,
),
)
]),
),
],
)));
}
}
When I create four listTiles in the emulator, two errors are given as follows
flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following RangeError was thrown building:
flutter: RangeError (index): Invalid value: Not in range 0..3, inclusive: 4
I hope someone can tell me what is wrong with my code. I am running on flutter version 1.3.10. Thanks in advance.
Also to the person that needs more code, here is the full code of main.dart. Hope this will help you find my errors

You are using title[index] but saving the value in title as title = taskTextList[index] which is not an array. So, you are getting range error.

Related

saving the State of the dropdownbuttons in flutter and exporting to excel

hello guys i'm a beginner on flutter and i'm having a little issue with keeping the changed values of dropdownbuttons alive ?? is there anyway to keep the result when the users changes the screen ?? as shown on the gif below .
and the code :
body: Column(
children: <Widget>[
Flexible(
child: ListView.builder(
itemCount: propositions.length,
itemExtent: 50.0,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text("${propositions[index]}"),
trailing: _dropdown(index),
);
},
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () => (null),
backgroundColor: Color.fromRGBO(82, 113, 255, 25),
child: const Icon(Icons.save),
),
bottomNavigationBar: BottomAppBar(
color: Color.fromRGBO(82, 113, 255, 25),
child: Container(height: 40.0),
shape: CircularNotchedRectangle(),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
Widget _dropdown(int index) {
return DropdownButton<String>(
isExpanded: false,
value: selectedItemValue[index].toString(),
items: _dropDownItem(),
onChanged: (value) {
setState(() {
selectedItemValue[index] = value as String;
});
},
);
}
List<DropdownMenuItem<String>> _dropDownItem() {
List<String> ddl = ["Not Done", "Partially Done", "Done"];
return ddl
.map((value) => DropdownMenuItem(
value: value,
child: Text(value),
))
.toList();
}
}
and i'm initiliazing the list with :
class _Check_listsState extends State<Check_lists> {
String dropdownValue = "Not Done";
List<String> selectedItemValue = <String>[];
#override
void initState() {
super.initState();
selectedItemValue.addAll(List.filled(propositions.length, "Not Done"));
}
and when i tried to use AutomaticKeepAliveClientMixin my app crashes , thnks

Passing value to previous widget

I have simple form , inside it have CircularAvatar when this is pressed show ModalBottomSheet to choose between take picture from gallery or camera. To make my widget more compact , i separated it to some file.
FormDosenScreen (It's main screen)
DosenImagePicker (It's only CircularAvatar)
ModalBottomSheetPickImage (It's to show ModalBottomSheet)
The problem is , i don't know how to passing value from ModalBottomSheetPickImage to FormDosenScreen. Because value from ModalBottomSheetPickImage i will use to insert operation.
I only success passing from third Widget to second Widget , but when i passing again from second Widget to first widget the value is null, and i think the problem is passing from Second widget to first widget.
How can i passing from third Widget to first Widget ?
First Widget
class FormDosenScreen extends StatefulWidget {
static const routeNamed = '/formdosen-screen';
#override
_FormDosenScreenState createState() => _FormDosenScreenState();
}
class _FormDosenScreenState extends State<FormDosenScreen> {
String selectedFile;
#override
Widget build(BuildContext context) {
final detectKeyboardOpen = MediaQuery.of(context).viewInsets.bottom;
print('trigger');
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Tambah Dosen'),
actions: <Widget>[
PopupMenuButton(
itemBuilder: (_) => [
PopupMenuItem(
child: Text('Tambah Pelajaran'),
value: 'add_pelajaran',
),
],
onSelected: (String value) {
switch (value) {
case 'add_pelajaran':
Navigator.of(context).pushNamed(FormPelajaranScreen.routeNamed);
break;
default:
}
},
)
],
),
body: Stack(
fit: StackFit.expand,
children: <Widget>[
SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(height: 20),
DosenImagePicker(onPickedImage: (file) => selectedFile = file),
SizedBox(height: 20),
Card(
margin: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextFormFieldCustom(
onSaved: (value) {},
labelText: 'Nama Dosen',
),
SizedBox(height: 20),
TextFormFieldCustom(
onSaved: (value) {},
prefixIcon: Icon(Icons.email),
labelText: 'Email Dosen',
keyboardType: TextInputType.emailAddress,
),
SizedBox(height: 20),
TextFormFieldCustom(
onSaved: (value) {},
keyboardType: TextInputType.number,
inputFormatter: [
// InputNumberFormat(),
WhitelistingTextInputFormatter.digitsOnly
],
prefixIcon: Icon(Icons.local_phone),
labelText: 'Telepon Dosen',
),
],
),
),
),
SizedBox(height: kToolbarHeight),
],
),
),
Positioned(
child: Visibility(
visible: detectKeyboardOpen > 0 ? false : true,
child: RaisedButton(
onPressed: () {
print(selectedFile);
},
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
color: colorPallete.primaryColor,
child: Text(
'SIMPAN',
style: TextStyle(fontWeight: FontWeight.bold, fontFamily: AppConfig.headerFont),
),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
textTheme: ButtonTextTheme.primary,
),
),
bottom: kToolbarHeight / 2,
left: sizes.width(context) / 15,
right: sizes.width(context) / 15,
)
],
),
);
}
}
Second Widget
class DosenImagePicker extends StatefulWidget {
final Function(String file) onPickedImage;
DosenImagePicker({#required this.onPickedImage});
#override
DosenImagePickerState createState() => DosenImagePickerState();
}
class DosenImagePickerState extends State<DosenImagePicker> {
String selectedImage;
#override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.center,
child: InkWell(
onTap: () async {
await showModalBottomSheet(
context: context,
builder: (context) => ModalBottomSheetPickImage(
onPickedImage: (file) {
setState(() {
selectedImage = file;
widget.onPickedImage(selectedImage);
print('Hellooo dosen image picker $selectedImage');
});
},
),
);
},
child: CircleAvatar(
foregroundColor: colorPallete.black,
backgroundImage: selectedImage == null ? null : MemoryImage(base64.decode(selectedImage)),
radius: sizes.width(context) / 6,
backgroundColor: colorPallete.accentColor,
child: selectedImage == null ? Text('Pilih Gambar') : SizedBox(),
),
),
);
}
}
Third Widget
class ModalBottomSheetPickImage extends StatelessWidget {
final Function(String file) onPickedImage;
ModalBottomSheetPickImage({#required this.onPickedImage});
#override
Widget build(BuildContext context) {
return SizedBox(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Wrap(
alignment: WrapAlignment.spaceEvenly,
children: <Widget>[
InkWell(
onTap: () async {
final String resultBase64 =
await commonFunction.pickImage(quality: 80, returnFile: ReturnFile.BASE64);
onPickedImage(resultBase64);
},
child: CircleAvatar(
foregroundColor: colorPallete.white,
backgroundColor: colorPallete.green,
child: Icon(Icons.camera_alt),
),
),
InkWell(
onTap: () async {
final String resultBase64 =
await commonFunction.pickImage(returnFile: ReturnFile.BASE64, isCamera: false);
onPickedImage(resultBase64);
},
child: CircleAvatar(
foregroundColor: colorPallete.white,
backgroundColor: colorPallete.blue,
child: Icon(Icons.photo_library),
),
),
],
),
),
);
}
}
The cleanest and easiest way to do this is through Provider. It is one of the state management solutions you can use to pass values around the app as well as rebuild only the widgets that changed. (Ex: When the value of the Text widget changes). Here is how you can use Provider in your scenario:
This is how your model should look like:
class ImageModel extends ChangeNotifier {
String _base64Image;
get base64Image => _base64Image;
set base64Image(String base64Image) {
_base64Image = base64Image;
notifyListeners();
}
}
Don't forget to add getters and setters so that you can use notifyListeners() if you have any ui that depends on it.
Here is how you can access the values of ImageModel in your UI:
final model=Provider.of<ImageModel>(context,listen:false);
String image=model.base64Image; //get data
model.base64Image=resultBase64; //set your image data after you used ImagePicker
Here is how you can display your data in a Text Widget (Ideally, you should use Selector instead of Consumer so that the widget only rebuilds if the value its listening to changes):
#override
Widget build(BuildContext context) {
//other widgets
Selector<ImageModel, String>(
selector: (_, model) => model.base64Image,
builder: (_, image, __) {
return Text(image);
},
);
}
)
}
You could achieve this easily. If you are using Blocs.

Flutter not updating DropdownButton placed within a dialog when item is selected

I have an alertDialog containing a DropdownButton widget. Whenever I click on an option within the dropDown I want it to display the selected value. I have listed the code below along with 2 screenshots.
I believe this may be an issue with how flutter builds widget because when I placed the DropdownButton widget outside of the dialog it worked, however placing it within an alertDialog causes it to fail. I also noticed that if I clicked on an option in the DropdownButton and then exited and clicked on the dialog again the selected item would change. However, I want the selected value to change without the user having to tap out of the dialog and then back in.
^
The above image is the dialog when a user first clicks on it. At first the only selected item is "I'm not able to help". This value should change whenever a user clicks on the DropdownMenu widget and selects a different option such as "other".
^
These are the various options a user can click on within the dropdown menu. When a user clicks on it, the menu should update accordingly.
CODE:
Please note that I have defined _chosenValue as a global variable outside of the build function.
void _showDecline() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Decline Appointment Request"),
content: Container(
height: 100,
width: 200,
child: Column(
children: <Widget>[
new Text("Please select an option for why you declined."),
new DropdownButton<String>(
value: _chosenValue,
underline: Container(),
items: <String>['I\'m not able to help', 'Unclear description', 'Not available at set date and time', 'Other'].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value, style: TextStyle(fontWeight: FontWeight.w500),),
);
}).toList(),
onChanged: (String value) {
setState(() {
_chosenValue = value;
});
},
)
],
),
),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("Close"),
onPressed: () {},
},
),
],
);
},
);
}
setState will only update current StatefulWidget's Widget Build function.
You should use StatefulBuilder inside showDialog.
For your case just add StatefulBuilder as a parent of your DropDown widget, and use StateSetter when you want to update the StatefulBuilder's children.
It will only update the widget tree defined under StateFulBuilder builder function.
See the full code including stateFulBuilder at DartPad code StateFulBuilderDartPad.
For more information on StatefulBuilder head over to StateFulBuilder documentation page.
import 'dart:convert';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(home: HomePage());
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String _chosenValue;
void _showDecline() {
showDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return AlertDialog(
title: new Text("Decline Appointment Request"),
content:
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
new Text("Please select an option for why you declined."),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: new DropdownButton<String>(
hint: Text('Select one option'),
value: _chosenValue,
underline: Container(),
items: <String>[
'I\'m not able to help',
'Unclear description',
'Not available at set date and time',
'Other'
].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(
value,
style: TextStyle(fontWeight: FontWeight.w500),
),
);
}).toList(),
onChanged: (String value) {
setState(() {
_chosenValue = value;
});
},
)),
]),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: FlatButton(child: Text('Click'), onPressed: _showDecline),
),
),
);
}
}
Just check out the below example you have to use the statefulBuilder to change the state.
import 'dart:convert';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(home: HomePage());
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String _chosenValue;
void _showDecline() {
showDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState){
return AlertDialog(
title: new Text("Decline Appointment Request"),
content: Container(
height: 100,
width: 200,
child: Column(
children: <Widget>[
new Text("Please select an option for why you declined."),
new DropdownButton<String>(
hint: Text('Select one option'),
value: _chosenValue,
underline: Container(),
items: <String>[
'I\'m not able to help',
'Unclear description',
'Not available at set date and time',
'Other'
].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(
value,
style: TextStyle(fontWeight: FontWeight.w500),
),
);
}).toList(),
onChanged: (String value) {
setState(() {
_chosenValue = value;
});
},
)
],
),
),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: FlatButton(child: Text('Click'), onPressed: _showDecline),
),
),
);
}
}
Just let me know if it works.
onTap: () {
///___________________________________________________________________
// Get.defaultDialog(
// title: " وضعیت دزدگیر",
// middleText: "پیام اعلام وضعیت دزدگیر ارسال گردد؟",
// titleStyle: TextStyle(
// color: mainColor2, fontWeight: FontWeight.bold, fontSize: 16),
// middleTextStyle:
// TextStyle(color: mainColor6.withOpacity(0.9), fontSize: 15),
// );
///----------------------------------------------------------------------
// showDialog(
// context: context,
// builder: (context) => AlertDialog(
// content: Column(
// children: <Widget>[
// TextField(
// decoration: InputDecoration(
// icon: Icon(Icons.account_circle),
// labelText: 'Username',
// ),
// ),
// TextField(
// obscureText: true,
// decoration: InputDecoration(
// icon: Icon(Icons.lock),
// labelText: 'Password',
// ),
// ),
// ],
// ),
// ),
// );
///___________________________________________________________________
List<DropdownMenuItem<String>> listDrop = [];
String selected=null;
void loadData() {
listDrop.add(new DropdownMenuItem(
child: new Text("پایدار"),
value:"555",
));
listDrop.add(
new DropdownMenuItem(
child: new Text("لحظه ای"),
value:"444",
),
);
}
loadData();
Alert(
context: context,
title: "تنظیمات خروجی شماره ۱",
// desc: ".",
// image: Image.asset(
// "assets/settings.png",
// scale: 5,
// ),
content: Directionality(
textDirection: TextDirection.rtl,
child: Center(
child: Column(
children: <Widget>[
SizedBox(height: 20.0),
TextField(
keyboardType: TextInputType.text,
controller: _codeShargController,
decoration: InputDecoration(
labelText: 'نام خروجی',
hintText: '${out1.read('codeShargController')}',
),
),
SizedBox(height: 25.0),
Center(
child: DropdownButton(
underline: Container(
height: 1.5,
color: Colors.black26,
),
hint: Text("وضعیت عملکرد"),
items: listDrop,
isExpanded: true,
value: selected,
style: TextStyle(color: Colors.black, fontSize: 16),
onChanged: (newValue) {
selected = newValue;
// setState(() {});
setState(() { selected = newValue; });
},
),
),
SizedBox(height: 25.0),
],
),
),
),
// content: Column(
// children: <Widget>[
//
// SizedBox(height: 10.0),
//
// TextField(
//
// decoration: InputDecoration(
//
// icon: Icon(Icons.account_circle),
// labelText: 'Username',
// ),
// ),
// SizedBox(height: 10.0),
//
// TextField(
// obscureText: true,
// decoration: InputDecoration(
// icon: Icon(Icons.lock),
// labelText: 'Password',
// ),
// ),
// ],
// ),
buttons: [
DialogButton(
onPressed: () {
out1.write(
"codeShargController", _codeShargController.text);
Navigator.pop(context);
},
child: Text(
"ثبت",
style: TextStyle(color: Colors.white, fontSize: 20),
),
)
]).show();
///___________________________________________________________________
Try This ......
implement the alert on separate dart file and call it. that worked for me.
Important - there was used following dropdown plugin because that ui better for me...
Link - dropdown_button2: ^1.2.2
on main page call to the alert as follows.
import 'package:crmapp/pages/payment_history/payment_history_search_dialog.dart';
import 'package:flutter/material.dart';
class PaymentHistoryScreen extends StatefulWidget {
#override
_PaymentHistoryScreenState createState() => _PaymentHistoryScreenState();
}
class _PaymentHistoryScreenState extends State<PaymentHistoryScreen> {
ScrollController scrollController = new ScrollController();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
// Setting up AppBar
appBar: AppBar(
title: Text('Payment History'),
),
// Body
body: Container(
// your code here - you can use onpressed method in the body also.here I used it for floating button
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return new PaymentHistorySearchDialog(); //call the alert dart
}
);
},
child: Container
(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(100)),
),
child: Icon(Icons.search_sharp, size: 32, color: Colors.white,)
)
),
);
}
then code the alert dart as follows.
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class PaymentHistorySearchDialog extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return PaymentHistorySearchDialogState();
}
}
class PaymentHistorySearchDialogState extends State<PaymentHistorySearchDialog> {
String? selectedValue;
List<String> items = [
'All',
'Completed',
'Pending',
'Rejected',
];
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return new AlertDialog(
titlePadding: EdgeInsets.only(top: 20, left: 15, right: 15, bottom: 5),
contentPadding: EdgeInsets.only(
top: 15,
left: 15,
right: 15,
bottom: 5
),
title: Text(
'Search'.toUpperCase(),
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.w600,
fontFamily: "medium",
)
),
content: Container(
width: double.infinity,
height: 220,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
DropdownButtonHideUnderline(
child: DropdownButton2(
hint: Text(
'Select Status',
style: TextStyle(
fontSize: 14,
),
),
items: items
.map((item) =>
DropdownMenuItem<String>(
value: item,
child: Text(
item,
style: const TextStyle(
fontSize: 14,
),
),
))
.toList(),
value: selectedValue,
onChanged: (value) {
setState(() {
selectedValue = value as String;
//Navigator.of(context).pop();
});
print(value);
// selectedValue = value as String;
},
buttonHeight: 30,
buttonWidth: double.infinity,
itemHeight: 40,
buttonDecoration: BoxDecoration(
// borderRadius: BorderRadius.circular(14),
border: Border(
bottom: BorderSide(width: 1, color: Colors.black38),
),
),
buttonPadding: const EdgeInsets.only(bottom: 5, top: 5),
),
)
],
),
)
);
}
}

OnTap Function in the DropDownMenu Button in Flutter

I've tried to populate the dropdown menu button with the data from the SQLite database.
Then on the onTap Function I wanted to navigate to the selected category.
When I tap on the category it does not navigate.
I have saved each category with an id in the database which is used the identify the selected item.
Here is the code:
'''
class _HomeState extends State<Home> {
TodoService _todoService;
var _selectedValue;
var _categories = List<DropdownMenuItem>();
List<Todo>_todoList=List<Todo>();
#override
initState(){
super.initState();
_loadCategories();
}
_loadCategories() async {
var _categoryService = CategoryService();
var categories = await _categoryService.readCategory();
categories.forEach((category) {
setState(() {
_categories.add(DropdownMenuItem(
child: Text(category['name']),
value: category['name'],
onTap: ()=>Navigator.of(context).push(MaterialPageRoute(builder:(context)=>TodosByCategory(category: category['name'],))),
));
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _globalKey,
appBar: AppBar(
actions: <Widget>[
DropdownButtonHideUnderline(
child: DropdownButton(
value: _selectedValue,
items: _categories,
dropdownColor: Colors.blue,
style: TextStyle(color: Colors.white,fontSize: 16.0),
iconDisabledColor: Colors.white,
iconEnabledColor: Colors.white,
onChanged: (value) {
setState(() {
_selectedValue = value;
});
},
),
),
'''
Here is the todosByCategory():
'''
class _TodosByCategoryState extends State<TodosByCategory> {
List<Todo>_todoList=List<Todo>();
TodoService _todoService=TodoService();
#override
initState(){
super.initState();
getTodosByCategories();
}
getTodosByCategories()async{
var todos=await _todoService.readTodoByCategory(this.widget.category);
todos.forEach((todo){
setState(() {
var model= Todo();
model.title=todo['title'];
model.dueDate=todo['dueDate'];
_todoList.add(model);
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Todos By Category'),
),
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: _todoList.length,
itemBuilder: (context, index){
return Padding(
padding: EdgeInsets.only(top:8.0, left: 8.0, right: 8.0),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 8.0,
child: ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(_todoList[index].title)
],
),
subtitle: Text(_todoList[index].dueDate),
// trailing: Text(_todoList[index].dueDate),
),
),
);
},),
)
],
),
);
}
}
'''
Please help me out.
Instead of writing the navigation code inside onTap of DropdownMenuItem, you can write it inside onChanged of DropdownButton where you are also getting the category name string as the value. It should work then.

ListView.builder gives error: RenderBox was not laid out

My listview.builder gives me tons of Renderbox errors such as flutter:
Another exception was thrown: RenderBox was not laid out: RenderViewport#fa71e NEEDS-LAYOUT NEEDS-PAINT
And:
NoSuchMethodError: The method '<=' was called on null.
I tried adding a padding but to no avail. I am running on Flutter version 1.3.10.
What was initialised wrongly?
import 'package:flutter/material.dart';
void main() => runApp(TodoList());
class TodoList extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _TodoListState();
}
}
var TaskTextField;
List taskTextList = [];
var TaskIsImportant = false;
class _TodoListState extends State<TodoList> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("To-Do List V2"),
),
body: Column(
children: <Widget>[
Container(
child: TextField(
decoration: InputDecoration(
hintText: "Enter title of task to be added"),
onChanged: (taskTextField) {
setState(() {
TaskTextField = taskTextField;
print(TaskTextField);
});
},
),
margin: EdgeInsets.all(16.0),
),
CheckboxListTile(
title: Text("Important"),
activeColor: Colors.blue,
value: TaskIsImportant,
onChanged: (val) {
setState(() {
TaskIsImportant = !TaskIsImportant;
print(TaskIsImportant);
});
},
),
Container(
margin: EdgeInsetsDirectional.fromSTEB(118, 20, 118, 20),
child: Row(
children: <Widget>[
RaisedButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
if (TaskIsImportant) {
taskTextList.add("❗️$TaskTextField");
//taskTitleList.add(TaskDetailField);
} else {
taskTextList.add(TaskTextField);
//taskTitleList.add(TaskDetailField);
}
});
},
),
RaisedButton(
child: Icon(Icons.done_all),
onPressed: () {
setState(() {
taskTextList = [];
});
},
),
],
),
),
ListView.builder(
itemBuilder: (context, index) {
var title = taskTextList[index];
padding: EdgeInsets.all(16.0);
return ListView(
children: <Widget>[
Text(title),
],
);
},
),
],
),
),
);
}
}
Please change your ListView.builder to,
Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
var title = taskTextList[index];
padding: EdgeInsets.all(16.0);
return ListTile(
title: Text(title),
);
},
itemCount: taskTextList.length,
),
)
Hope this helps!
Wrap your Column children widgets in a Flexible widget, such as Expanded. Also, you should have a Stateless Widget as entry point to your app with your MaterialApp for example and then call the stateful from there.