hi im trying to create a scrollable form with text form field widgets and inside the form will be a list view of widgets all this should be displayed on a dialog. This is my code for the form itself not the dialog.
import 'dart:developer' as dev;
import 'package:flutter/material.dart';
import 'package:track/src/features/invoices/model/invoice.dart';
import 'package:track/src/features/invoices/application/pdf_invoice_api.dart';
class InvoiceForm extends StatefulWidget {
Invoice invoice;
InvoiceForm({Key? key, required this.invoice}) : super(key: key);
@override
State<InvoiceForm> createState() => _InvoiceFormState();
}
class _InvoiceFormState extends State<InvoiceForm> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: TextEditingController()..text = widget.invoice.client,
validator: (value) {
value!.isEmpty ? 'Enter a value for client' : null;
},
style: Theme.of(context).textTheme.labelMedium,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
labelText: 'Client:',
labelStyle: Theme.of(context).textTheme.labelMedium),
),
Expanded(
child: ListView.builder(
itemCount: widget.invoice.items.length,
itemBuilder: (context, index) {
final item = widget.invoice.items[index];
return ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20),
itemTextFormField(
initialValue: item.name,
labelText: 'Name',
index: index,
),
itemTextFormField(
initialValue: item.description,
index: index,
labelText: 'description',
),
itemTextFormField(
initialValue: item.quantity.toString(),
index: index,
labelText: 'quantity'),
itemTextFormField(
initialValue: item.costBeforeVAT.toString(),
index: index,
labelText: 'Before VAT'),
]),
);
}),
),
Align(
alignment: Alignment.bottomRight,
child: IconButton(
onPressed: () async {
_formKey.currentState!.save();
Navigator.pop(context);
await PdfInvoiceApi.generate(widget.invoice);
},
icon: Icon(Icons.send)))
],
),
),
);
}
Widget itemTextFormField({
required String initialValue,
required String labelText,
required int index,
}) {
return TextFormField(
controller: TextEditingController()..text = initialValue,
onSaved: (newValue) {
if (newValue!.isNotEmpty) {
switch (labelText) {
case 'Name':
widget.invoice.items[index].name = newValue;
break;
case 'Description':
widget.invoice.items[index].description = newValue;
break;
case 'Quantity':
widget.invoice.items[index].quantity = int.parse(newValue);
break;
case 'Before VAT':
widget.invoice.items[index].quantity = int.parse(newValue);
}
}
},
style: Theme.of(context).textTheme.labelMedium,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
labelText: 'Item:',
labelStyle: Theme.of(context).textTheme.labelMedium,
),
);
}
}
This is error I am recieving:
======= Exception caught by rendering library =====================================================
The following assertion was thrown during performLayout():
Assertion failed: file:///home/ranvir/.local/share/ProgrammingFrameworks/flutter/packages/flutter/lib/src/rendering/box.dart:2009:12
hasSize
"RenderBox was not laid out: RenderMouseRegion#86185 relayoutBoundary=up8 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE"
The relevant error-causing widget was:
SingleChildScrollView SingleChildScrollView:file:///home/ranvir/AndroidStudioProjects/track/lib/src/features/invoices/presentation/invoice_dialog_form.dart:22:12
When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49 throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 29:3 assertFailed
performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/layout_helper.dart 56:10 layoutChild
packages/flutter/src/rendering/flex.dart 903:45 [_computeSizes]
packages/flutter/src/rendering/flex.dart 938:32 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/shifted_box.dart 240:5 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 297:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/custom_paint.dart 552:11 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/proxy_box.dart 1467:11 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 297:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/shifted_box.dart 442:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/shifted_box.dart 240:5 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/shifted_box.dart 240:5 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/shifted_box.dart 240:5 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/proxy_box.dart 3815:13 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/widgets/overlay.dart 852:14 performLayout
packages/flutter/src/rendering/object.dart 2007:7 [_layoutWithoutResize]
packages/flutter/src/rendering/object.dart 1020:17 flushLayout
packages/flutter/src/rendering/binding.dart 516:19 drawFrame
packages/flutter/src/widgets/binding.dart 869:13 drawFrame
packages/flutter/src/rendering/binding.dart 381:5 [_handlePersistentFrameCallback]
packages/flutter/src/scheduler/binding.dart 1275:15 [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1204:9 handleDrawFrame
packages/flutter/src/scheduler/binding.dart 1062:5 [_handleDrawFrame]
lib/_engine/engine/platform_dispatcher.dart 1168:13 invoke
lib/_engine/engine/platform_dispatcher.dart 218:5 invokeOnDrawFrame
lib/_engine/engine/initialization.dart 186:45 <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 352:37 _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 357:39 dcall
The following RenderObject was being processed when the exception was fired: RenderPointerListener#f8e6f relayoutBoundary=up7 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
... size: MISSING
... behavior: deferToChild
... listeners: down, panZoomStart
RenderObject: RenderPointerListener#f8e6f relayoutBoundary=up7 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
parentData: <none> (can use size)
constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
size: MISSING
behavior: deferToChild
listeners: down, panZoomStart
... child: RenderMouseRegion#86185 relayoutBoundary=up8 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
... size: MISSING
... behavior: opaque
... listeners: hover, exit
... child: RenderCustomPaint#d0e0e relayoutBoundary=up9 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
... size: MISSING
... painter: null
... foregroundPainter: ScrollbarPainter#d9c98
... child: RenderRepaintBoundary#db202 relayoutBoundary=up10 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... needs compositing
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
... size: MISSING
... usefulness ratio: no metrics collected yet (never painted)
... child: _RenderScrollSemantics#773d3 relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
... semantic boundary
... size: MISSING
====================================================================================================
======== Exception caught by rendering library =====================================================
The following assertion was thrown during performLayout():
Assertion failed: file:///home/ranvir/.local/share/ProgrammingFrameworks/flutter/packages/flutter/lib/src/rendering/box.dart:2009:12
hasSize
"RenderBox was not laid out: RenderPointerListener#f8e6f relayoutBoundary=up7 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE"
The relevant error-causing widget was:
SingleChildScrollView SingleChildScrollView:file:///home/ranvir/AndroidStudioProjects/track/lib/src/features/invoices/presentation/invoice_dialog_form.dart:22:12
When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49 throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 29:3 assertFailed
packages/flutter/src/rendering/box.dart 2009:12 get size
packages/flutter/src/rendering/proxy_box.dart 121:14 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
packages/flutter/src/rendering/object.dart 2169:7 layout
packages/flutter/src/rendering/box.dart 2430:11 layout
packages/flutter/src/rendering/proxy_box.dart 120:7 performLayout
invokeOnDrawFrame
lib/_engine/engine/initialization.dart 186:45 <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 352:37 _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 357:39 dcall
The following RenderObject was being processed when the exception was fired: RenderSemanticsGestureHandler#7dc89 relayoutBoundary=up6 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
... size: MISSING
... behavior: deferToChild
... gestures: <none>
RenderObject: RenderSemanticsGestureHandler#7dc89 relayoutBoundary=up6 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
parentData: <none> (can use size)
constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
size: MISSING
behavior: deferToChild
gestures: <none>
... child: RenderPointerListener#f8e6f relayoutBoundary=up7 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
... size: MISSING
... behavior: deferToChild
... listeners: down, panZoomStart
... child: RenderMouseRegion#86185 relayoutBoundary=up8 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
... size: MISSING
... behavior: opaque
... listeners: hover, exit
... child: RenderCustomPaint#d0e0e relayoutBoundary=up9 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
... size: MISSING
... painter: null
... foregroundPainter: ScrollbarPainter#d9c98
... child: RenderRepaintBoundary#db202 relayoutBoundary=up10 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... needs compositing
... parentData: <none> (can use size)
... constraints: BoxConstraints(w=810.0, 0.0<=h<=Infinity)
... size: MISSING
... usefulness ratio: no metrics collected yet (never painted)
====================================================================================================
I can get it to display without the listveiw builder but ofc I need that, so user can add delete a set of form fields at same time. So is there a solution?
Edit 2: After removing the Exapanded widget and applying shrink wrap I got this:
But replacing form fields with text widgets works:
ListView.builder(
shrinkWrap: true,
itemCount: widget.invoice.items.length,
itemBuilder: (context, index) {
final item = widget.invoice.items[index];
return ListTile(title: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(item.name),
SizedBox(width: 10,), Text(item.description),
// SizedBox(height: 20),
// itemTextFormField(
// initialValue: item.name,
// labelText: 'Name', index: index,),
// itemTextFormField(
// initialValue: item.description, index: index, labelText: 'description',
// ),
// itemTextFormField(
// initialValue: item.quantity.toString(),
// index: index, labelText: 'quantity'),
// itemTextFormField(
// initialValue: item.costBeforeVAT.toString(),
// index: index, labelText: 'Before VAT'),
],),);},),
Edit 3: Tearing down the code a bit more showed that I could have the text form fields inside the title. The problem comes with inserting the row widget.
ListView.builder(
shrinkWrap: true,
itemCount: widget.invoice.items.length,
itemBuilder: (context, index) {
final item = widget.invoice.items[index];
return ListTile(
title: itemTextFormField(
initialValue: item.name,
labelText: 'name',
index: index));
},
),
This works but is not what I want
CodePudding user response:
You can't use Expanded
in the SingleChildScrollView
or other scrollable widgets, so remove the Expanded
Widget and use shrinkWrap: true
for your ListView.builder
like this:
class InvoiceForm extends StatefulWidget {
Invoice invoice;
InvoiceForm({Key? key, required this.invoice}) : super(key: key);
@override
State<InvoiceForm> createState() => _InvoiceFormState();
}
class _InvoiceFormState extends State<InvoiceForm> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: TextEditingController()..text = widget.invoice.client,
validator: (value) {
value!.isEmpty ? 'Enter a value for client' : null;
},
style: Theme.of(context).textTheme.labelMedium,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
labelText: 'Client:',
labelStyle: Theme.of(context).textTheme.labelMedium),
),
ListView.builder(
shrinkWrap: true,
itemCount: widget.invoice.items.length,
itemBuilder: (context, index) {
final item = widget.invoice.items[index];
return ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20),
Expanded(
child: itemTextFormField(
initialValue: item.name,
labelText: 'Name',
index: index,
),
),
Expanded(
child: itemTextFormField(
initialValue: item.description,
index: index,
labelText: 'description',
),
),
Expanded(
child: itemTextFormField(
initialValue: item.quantity.toString(),
index: index,
labelText: 'quantity',
),
),
Expanded(
child: itemTextFormField(
initialValue: item.costBeforeVAT.toString(),
index: index,
labelText: 'Before VAT',
),
),
]),
);
}),
Align(
alignment: Alignment.bottomRight,
child: IconButton(
onPressed: () async {
_formKey.currentState!.save();
Navigator.pop(context);
await PdfInvoiceApi.generate(widget.invoice);
},
icon: Icon(Icons.send)))
],
),
),
);
}
Widget itemTextFormField({
required String initialValue,
required String labelText,
required int index,
}) {
return TextFormField(
controller: TextEditingController()..text = initialValue,
onSaved: (newValue) {
if (newValue!.isNotEmpty) {
switch (labelText) {
case 'Name':
widget.invoice.items[index].name = newValue;
break;
case 'Description':
widget.invoice.items[index].description = newValue;
break;
case 'Quantity':
widget.invoice.items[index].quantity = int.parse(newValue);
break;
case 'Before VAT':
widget.invoice.items[index].quantity = int.parse(newValue);
}
}
},
style: Theme.of(context).textTheme.labelMedium,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
labelText: 'Item:',
labelStyle: Theme.of(context).textTheme.labelMedium,
),
);
}
}
Also, you need to put your itemTextFormField in an Expanded widget when you use this in a row:
Expanded(
child: itemTextFormField(
initialValue: item.name,
labelText: 'Name',
index: index,
),
),
Expanded(
child: itemTextFormField(
initialValue: item.description,
index: index,
labelText: 'description',
),
),
Expanded(
child: itemTextFormField(
initialValue: item.quantity.toString(),
index: index,
labelText: 'quantity',
),
),
Expanded(
child: itemTextFormField(
initialValue: item.costBeforeVAT.toString(),
index: index,
labelText: 'Before VAT',
),
),