Home > Software engineering >  Flutter create scrollable from widget built manual and generated textform builds inside listview on
Flutter create scrollable from widget built manual and generated textform builds inside listview on

Time:10-30

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: Dialog Form Error

But replacing form fields with text widgets works: Dialog From Text Widget replaced form fields

            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',
                        ),
                      ),
  • Related