1

I was trying to receive data from an API in a ListView Builder using user input to display how many tickets to be displayed.. This is where I am trying to reflect the user input. Everytime I am using the textfield before the listview builder I am receving error

    import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

class Ticket {
  Ticket({
    this.tickets,
  });

  List<List<List<int>>> tickets;

  factory Ticket.fromJson(Map<String, dynamic> json) => Ticket(
        tickets: List<List<List<int>>>.from(json["tickets"].map((x) =>
            List<List<int>>.from(
                x.map((x) => List<int>.from(x.map((x) => x)))))),
      );

  Map<String, dynamic> toJson() => {
        "tickets": List<dynamic>.from(tickets.map((x) => List<dynamic>.from(
            x.map((x) => List<dynamic>.from(x.map((x) => x)))))),
      };
}

class TicketPage extends StatefulWidget {
  @override
  _TicketPageState createState() => _TicketPageState();
}

class _TicketPageState extends State<TicketPage> {
  String _nos = '0';
  Ticket ticketList;
  String apiResult;
  Map<String, bool> cellStatus = {};
  final numCon = TextEditingController();

  @override
  void initState() {
    super.initState();
    _getNumbers();
    numCon.addListener(_updateUserInput);
  }

  _updateUserInput() {
    _nos = numCon.text;
  }

  @override
  void dispose() {
// Clean up the controller when the widget is removed from the widget tree.
// This also removes the listener.
    numCon.dispose();
    super.dispose();
  }

  _getNumbers() async {
    var result = await http
        .post(
            'https://tickets-qzd55332wa-de.a.run.app/generateTickets?ticketsRequired=$_nos')
        .then((result) {
      //Waits for the API response and assigns to apiResult variable
      setState(() {
        apiResult = result.body;
      });
    });
  }

  // List tick = [
  //   {
  //     'tickets': [
  //       [
  //         [11, 5, 7, 10, 28, 9, 7, 74, 59],
  //         [1, 15, 7, 10, 8, 79, 27, 74, 9],
  //         [71, 5, 7, 20, 18, 9, 77, 74, 79],
  //       ],
  //       [
  //         [21, 5, 7, 80, 8, 9, 7, 74, 49],
  //         [31, 15, 7, 10, 18, 79, 7, 74, 19],
  //         [71, 5, 7, 20, 18, 79, 77, 74, 29],
  //       ],
  //     ]
  //   },
  // ];

  @override
  Widget build(BuildContext context) {
    var h = MediaQuery.of(context).size.height;
    var w = MediaQuery.of(context).size.width;

    if (apiResult == null) {
      return Scaffold(body: Center(child: CircularProgressIndicator()));
    } else {
      //Get an instance of Ticket from the API assigned to apiResponse variable
      ticketList = Ticket.fromJson(json.decode(apiResult));
      print('Tickets: ${ticketList.tickets}');

      return Scaffold(
        body: SafeArea(
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.all(28.0),
                child: Container(
                  child: TextField(
                    controller: numCon,
                    decoration: InputDecoration(
                      hintText: 'nos',
                    ),
                  ),
                ),
              ),
              RaisedButton(onPressed: () {
                setState(() {
                  _getNumbers();
                });
              }),
              Center(
                child: Padding(
                  padding: const EdgeInsets.all(20.0),
                  child: Container(
                    decoration: BoxDecoration(
                        border: Border.all(
                      color: Colors.black,
                    )),
                    child: ListView.builder(
                      itemCount: ticketList.tickets.length,
                      itemBuilder: (BuildContext context, index) {
                        List tripleNumbersList = [];
                        List<Widget> cells = [];
                        List<Widget> rows = [];

                        //Get the lists of lists inside the 'tickets' list
                        tripleNumbersList = ticketList.tickets[index];
                        //Iterates over each list with other 3 lists
                        for (int j = 0; j < tripleNumbersList.length; j++) {
                          //Get one of the 3 lists
                          List<int> list = tripleNumbersList[j];
                          //Iterates over the list of numbers
                          for (int k = 0; k < list.length; k++) {
                            //Adds a Widget to 'cells; list for each number
                            cells.add(Container(
                                height: 40,
                                width: 40,
                                decoration: BoxDecoration(
                                  border: Border.all(
                                    color: Colors.black,
                                  ),
                                  //color: Colors.pink
                                ),
                                child: GestureDetector(
                                  onTap: () {
                                    print('Working');
                                    if (cellStatus['$j$k'] ?? true) {
                                      print('Working');
                                      setState(() {
                                        cellStatus.addAll({'$j$k': false});
                                      });
                                    }
                                  },
                                  child: list[k] != 0
                                      ? Text(
                                          ' ${list[k]}  ',
                                          style: TextStyle(
                                              fontSize: 18.0,
                                              fontWeight: FontWeight.bold),
                                        )
                                      : Text(''),
                                )));
                          }
                          //Adds the list of 'cells' in the 'rows' list
                          rows.add(Row(children: cells));
                          cells = [];
                        }
                        //Adds a empty row to make space
                        rows.add(Row(children: [
                          Container(
                            height: 10,
                          )
                        ]));

                        return Center(
                          child: Container(
                            height: h / 5,
                            decoration: BoxDecoration(
                              border: Border.all(
                                color: Colors.black,
                              ),
                              //color: Colors.pink
                            ),
                            child: Column(
                              //Adds the list of rows to the column
                              children: rows,
                            ),
                          ),
                        );
                      },
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      );
    }
  }
}

And it is throwing exception as

RenderBox was not laid out: RenderCustomPaint#aecb2 relayoutBoundary=up8 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1694 pos 12: 'hasSize'
The relevant error-causing widget was
    ListView 
RenderBox was not laid out: RenderPadding#d9b88 relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1694 pos 12: 'hasSize'
The relevant error-causing widget was
    Scaffold 

I hope I could explain the problem the and wish to see help me out solve this issue. I am stuck to this problem a from a lot.

Pratyay Sinha
  • 511
  • 1
  • 6
  • 16

1 Answers1

1

The error occurs due to nesting of ListView inside Column.

The above code can be modified to wrap ListView in Expanded. With reference to this answer

Example :

  @override
  Widget build(BuildContext context) {
    return _buildList(context);
  }

  Widget _buildList(BuildContext context) {
    var h = MediaQuery.of(context).size.height;

    if (apiResult == null) {
      return Scaffold(body: Center(child: CircularProgressIndicator()));
    } else {
      //Get an instance of Ticket from the API assigned to apiResponse variable
      ticketList = Ticket.fromJson(json.decode(apiResult));
      print('${ticketList.tickets.length} Tickets: ${ticketList.tickets}');

      return SafeArea(
        child: Scaffold(
          appBar: AppBar(
            title: Text('SO 62967820'),
          ),
          body: Column(
            children: [
              Padding(
                padding: const EdgeInsets.all(28.0),
                child: Container(
                  child: TextField(
                    controller: numCon,
                    decoration: InputDecoration(
                      hintText: 'nos',
                    ),
                  ),
                ),
              ),
              RaisedButton(
                  child: Text('Generate'),
                  onPressed: () {
                    setState(() {
                      _getNumbers();
                    });
                  }),
              Expanded(
                child: ListView.builder(
                  itemCount: ticketList.tickets.length,
                  itemBuilder: (BuildContext context, index) {
                    List tripleNumbersList = [];
                    List<Widget> cells = [];
                    List<Widget> rows = [];

                    //Get the lists of lists inside the 'tickets' list
                    tripleNumbersList = ticketList.tickets[index];
                    //Iterates over each list with other 3 lists
                    for (int j = 0; j < tripleNumbersList.length; j++) {
                      //Get one of the 3 lists
                      List<int> list = tripleNumbersList[j];
                      //Iterates over the list of numbers
                      for (int k = 0; k < list.length; k++) {
                        //Adds a Widget to 'cells; list for each number
                        cells.add(Container(
                            height: 40,
                            width: 40,
                            decoration: BoxDecoration(
                              border: Border.all(
                                color: Colors.black,
                              ),
                              //color: Colors.pink
                            ),
                            child: GestureDetector(
                              onTap: () {
                                print('Working');
                                if (cellStatus['$j$k'] ?? true) {
                                  print('Working');
                                  setState(() {
                                    cellStatus.addAll({'$j$k': false});
                                  });
                                }
                              },
                              child: list[k] != 0
                                  ? Text(
                                      ' ${list[k]}  ',
                                      style: TextStyle(
                                          fontSize: 18.0,
                                          fontWeight: FontWeight.bold),
                                    )
                                  : Text(''),
                            )));
                      }
                      //Adds the list of 'cells' in the 'rows' list
                      rows.add(Row(children: cells));
                      cells = [];
                    }
                    //Adds a empty row to make space
                    rows.add(Row(children: [
                      Container(
                        height: 10,
                      )
                    ]));

                    return Center(
                      child: Container(
                        height: h / 5,
                        decoration: BoxDecoration(
                          border: Border.all(
                            color: Colors.black,
                          ),
                          //color: Colors.pink
                        ),
                        child: Column(
                          //Adds the list of rows to the column
                          children: rows,
                        ),
                      ),
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      );
    }
  }
dev-aentgs
  • 1,218
  • 2
  • 9
  • 17
  • But what role did that expanded widget play – Pratyay Sinha Jul 18 '20 at 17:24
  • Not completely sure but from my understanding of the error and the explanation from [this answer](https://stackoverflow.com/a/49506624/13625305), the `Expanded` widget took care of allocating appropriate height for the `ListView` in the parent `Column`. @PratyaySinha – dev-aentgs Jul 19 '20 at 05:35
  • Hey!! Would appreciate if you could just have a look at this problem that I am facing https://stackoverflow.com/questions/68603763/i-am-trying-to-store-the-authorization-token-fetched-from-the-rest-api-and-then – Pratyay Sinha Jul 31 '21 at 16:12