Search code examples
flutterdartscrollview

BoxConstraints force infinite width. Probable cause: _RenderListTile._layoutBox. Offending constraints: BoxConstraints(w=Infinity, 0.0<=h<=Infinity)


I'm encountering an error in my Flutter app and seeking assistance to resolve it. Here's the error message:

FlutterError (BoxConstraints forces an infinite width.
These invalid constraints were provided to RenderParagraph's layout() function by the following function, which probably computed the invalid constraints in question:
  _RenderListTile._layoutBox (package:flutter/src/material/list_tile.dart:1274:9)
The offending constraints were:
  BoxConstraints(w=Infinity, 0.0<=h<=Infinity))

Code Snippet:

import 'package:blood_token_app/models/services_model/blood_request_model.dart';
import 'package:blood_token_app/screens/main_screens/details_screen.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_svg/svg.dart';

class MainScreen extends StatefulWidget {
  const MainScreen({Key? key}) : super(key: key);

  @override
  State<MainScreen> createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  @override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;

    return Scaffold(
      appBar: AppBar(
        title: Text('Blood Token'),
      ),
      body: Container(
        height: size.height,
        width: size.width,
        child: SingleChildScrollView(
          child: Column(
            children: [
              SizedBox(
                child: Padding(
                  padding:
                      const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
                  child: Center(
                    child: Card(
                      color: Theme.of(context).scaffoldBackgroundColor,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(20),
                      ),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: [
                          SvgPicture.asset(
                            "assets/logos/032-blood_bag.svg",
                            height: size.height * 0.18,
                          ),
                          Text(
                            "Donate Blood\n Save Lives",
                            textAlign: TextAlign.center,
                            style: TextStyle(
                              fontSize: size.height * 0.030,
                              color: Colors.black,
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
              Column(
                children: [
                  ListTile(
                    title: Text(
                      'Current Requests',
                      style: TextStyle(fontSize: 20.0),
                    ),
                    trailing: Text('See all'),
                  ),
                  Expanded(
                    child: StreamBuilder<QuerySnapshot>(
                      stream: FirebaseFirestore.instance
                          .collection('blood_requests')
                          .snapshots(),
                      builder: (context, snapshot) {
                        if (snapshot.connectionState ==
                            ConnectionState.waiting) {
                          return AppUtils.customProgressIndicator();
                        }
                        if (snapshot.hasError) {
                          return Text('Error: ${snapshot.error}');
                        }
                        final List<BloodRequestModel> bloodRequests = snapshot
                            .data!.docs
                            .map((doc) => BloodRequestModel.fromJson(
                                doc.data() as Map<String, dynamic>))
                            .toList();

                        return Container(
                          width: MediaQuery.of(context)
                              .size
                              .width, // Ensure finite width
                          child: SingleChildScrollView(
                            scrollDirection: Axis.horizontal,
                            child: Row(
                              children: bloodRequests.map((value) {
                                return Padding(
                                  padding: const EdgeInsets.symmetric(
                                      horizontal: 10, vertical: 10),
                                  child: Container(
                                    width:
                                        300, // Set a finite width as per your design
                                    decoration: BoxDecoration(
                                      shape: BoxShape.rectangle,
                                      boxShadow: [
                                        BoxShadow(
                                          color: Colors.grey.withOpacity(0.5),
                                          spreadRadius: 5,
                                          blurRadius: 7,
                                          offset: Offset(0, 3),
                                        ),
                                      ],
                                      color: Theme.of(context)
                                          .scaffoldBackgroundColor,
                                      borderRadius: BorderRadius.circular(20.0),
                                      border: Border.all(
                                        color: Colors.grey.shade100,
                                        width: 0.0,
                                      ),
                                    ),
                                    child: Column(
                                      crossAxisAlignment:
                                          CrossAxisAlignment.start,
                                      children: [
                                        ListTile(
                                          title: Text(
                                            "Requester Name",
                                            textAlign: TextAlign.left,
                                            overflow: TextOverflow.ellipsis,
                                          ),
                                          subtitle: Text(
                                            "${value.requesterName}",
                                            textAlign: TextAlign.left,
                                            overflow: TextOverflow.ellipsis,
                                          ),
                                          trailing: Column(
                                            mainAxisAlignment:
                                                MainAxisAlignment.center,
                                            children: [
                                              Text("Urgency Level"),
                                              Text(
                                                "${value.urgencyLevel}",
                                                textAlign: TextAlign.left,
                                                overflow: TextOverflow.ellipsis,
                                              ),
                                            ],
                                          ),
                                        ),
                                        ListTile(
                                          title: Text("Location"),
                                          subtitle:
                                              Text("${value.customLocation}"),
                                          trailing: Column(
                                            mainAxisAlignment:
                                                MainAxisAlignment.center,
                                            children: [
                                              Text("Blood Type"),
                                              Text("${value.bloodType}"),
                                            ],
                                          ),
                                        ),
                                        ListTile(
                                          leading: Icon(Icons.watch_outlined),
                                          title: Text(
                                              "${value.formattedTimestamp()}"),
                                        ),
                                        MaterialButton(
                                          shape: RoundedRectangleBorder(
                                            borderRadius: BorderRadius.only(
                                              bottomLeft: Radius.circular(20),
                                              bottomRight: Radius.circular(20),
                                            ),
                                          ),
                                          height: size.height * 0.060,
                                          minWidth: size.width,
                                          color: AppUtils.redColor,
                                          onPressed: () {
                                            if (mounted) {
                                              Navigator.push(context,
                                                  MaterialPageRoute(
                                                      builder: (_) {
                                                return DetailsScreen(
                                                    requesterName:
                                                        value.requesterName,
                                                    bloodType: value.bloodType,
                                                    quantityNeeded:
                                                        value.quantityNeeded,
                                                    urgencyLevel:
                                                        value.urgencyLevel,
                                                    location: value.location,
                                                    contactNumber:
                                                        value.contactNumber,
                                                    patientName:
                                                        value.patientName,
                                                    date: value
                                                        .formattedTimestamp(),
                                                    customLocation:
                                                        value.customLocation,
                                                    // Convert latitude string to double
                                                    latitude: double.parse(value
                                                        .location!
                                                        .split(', ')[0]),
                                                    // Convert longitude string to double
                                                    longitude: double.parse(
                                                        value.location!
                                                            .split(', ')[1]));
                                              }));
                                            }
                                          },
                                          child: Text(
                                            "Details",
                                            style: TextStyle(
                                              color: AppUtils.whiteColor,
                                            ),
                                          ),
                                        ),
                                      ],
                                    ),
                                  ),
                                );
                              }).toList(),
                            ),
                          ),
                        );
                      },
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

What did you try and what were you expecting?

I attempted to make a card scrollable horizontally by using a ListView wrapped with SingleChildScrollView inside a Column. I expected the cards containing blood donation requests to scroll horizontally, allowing users to view multiple requests. However, I encountered an error stating:

Exception has occurred.
FlutterError (BoxConstraints forces an infinite width.
These invalid constraints were provided to RenderParagraph's layout() function by the following function, which probably computed the invalid constraints in question:
  _RenderListTile._layoutBox (package:flutter/src/material/list_tile.dart:1274:9)
The offending constraints were:
  BoxConstraints(w=Infinity, 0.0<=h<=Infinity))

I expected the cards to scroll smoothly, displaying all the donation requests horizontally within the available screen width. However, the error message indicated that there was an issue with constraints, particularly with regards to width.


Solution

  • Remove the Expanded widget above the StreamBuilder, you can't expand within a scroll view.

    StreamBuilder still inside the SingleChildScrollView, you can't expand within.

    I tried to run your code with dummy data and here's the result:

    enter image description here

    and here's your widget, i have used a dummy stream to mock your data:

    class MainScreen extends StatefulWidget {
      const MainScreen({Key? key}) : super(key: key);
    
      @override
      State<MainScreen> createState() => _MainScreenState();
    }
    
    class _MainScreenState extends State<MainScreen> {
      @override
      Widget build(BuildContext context) {
        final Size size = MediaQuery.of(context).size;
    
        return Scaffold(
          appBar: AppBar(
            title: Text('Blood Token'),
          ),
          body: Container(
            height: size.height,
            width: size.width,
            child: SingleChildScrollView(
              child: Column(
                children: [
                  SizedBox(
                    child: Padding(
                      padding:
                          const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
                      child: Center(
                        child: Card(
                          color: Theme.of(context).scaffoldBackgroundColor,
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(20),
                          ),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                            children: [
                              Container(
                                width: 100,
                                height: 100,
                                color: Colors.purple,
                                child: Text(
                                  'Your Picture'
                              ,
                              style: TextStyle(
                                color: Colors.white,
                              )
                                )
                              ),
                              Text(
                                "Donate Blood\n Save Lives",
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                  fontSize: size.height * 0.030,
                                  color: Colors.black,
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ),
                  Column(
                    children: [
                      ListTile(
                        title: Text(
                          'Current Requests',
                          style: TextStyle(fontSize: 20.0),
                        ),
                        trailing: Text('See all'),
                      ),
                      StreamBuilder(
                        stream: getStream(),
                        builder: (context, snapshot) {
                          if (snapshot.connectionState ==
                              ConnectionState.waiting) {
                            return CircularProgressIndicator();
                          }
                          if (snapshot.hasError) {
                            return Text('Error: ${snapshot.error}');
                          }
                          final list = [for(int i = 0 ; i < 10 ; i++) i];
    
                          return Container(
                            width: MediaQuery.of(context)
                                .size
                                .width, // Ensure finite width
                            child: SingleChildScrollView(
                              scrollDirection: Axis.horizontal,
                              child: Row(
                                children: list.map((value) {
                                  return Padding(
                                    padding: const EdgeInsets.symmetric(
                                        horizontal: 10, vertical: 10),
                                    child: Container(
                                      width:
                                          300, // Set a finite width as per your design
                                      decoration: BoxDecoration(
                                        shape: BoxShape.rectangle,
                                        boxShadow: [
                                          BoxShadow(
                                            color: Colors.grey.withOpacity(0.5),
                                            spreadRadius: 5,
                                            blurRadius: 7,
                                            offset: Offset(0, 3),
                                          ),
                                        ],
                                        color: Theme.of(context)
                                            .scaffoldBackgroundColor,
                                        borderRadius: BorderRadius.circular(20.0),
                                        border: Border.all(
                                          color: Colors.grey.shade100,
                                          width: 0.0,
                                        ),
                                      ),
                                      child: Column(
                                        crossAxisAlignment:
                                            CrossAxisAlignment.start,
                                        children: [
                                          ListTile(
                                            title: Text(
                                              "Requester Name",
                                              textAlign: TextAlign.left,
                                              overflow: TextOverflow.ellipsis,
                                            ),
                                            subtitle: Text(
                                              "${value}",
                                              textAlign: TextAlign.left,
                                              overflow: TextOverflow.ellipsis,
                                            ),
                                            trailing: Column(
                                              mainAxisAlignment:
                                                  MainAxisAlignment.center,
                                              children: [
                                                Text("Urgency Level"),
                                                Text(
                                                  "${value}",
                                                  textAlign: TextAlign.left,
                                                  overflow: TextOverflow.ellipsis,
                                                ),
                                              ],
                                            ),
                                          ),
                                          ListTile(
                                            title: Text("Location"),
                                            subtitle:
                                                Text("${value}"),
                                            trailing: Column(
                                              mainAxisAlignment:
                                                  MainAxisAlignment.center,
                                              children: [
                                                Text("Blood Type"),
                                                Text("${value}"),
                                              ],
                                            ),
                                          ),
                                          ListTile(
                                            leading: Icon(Icons.watch_outlined),
                                            title: Text(
                                                "${value}"),
                                          ),
                                          MaterialButton(
                                            shape: RoundedRectangleBorder(
                                              borderRadius: BorderRadius.only(
                                                bottomLeft: Radius.circular(20),
                                                bottomRight: Radius.circular(20),
                                              ),
                                            ),
                                            height: size.height * 0.060,
                                            minWidth: size.width,
                                            color: Colors.red,
                                            onPressed: () {
                    
                                              },
                                          
                                            child: Text(
                                              "Details",
                                              style: TextStyle(
                                                color: Colors.orange,
                                              ),
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                  );
                                }).toList(),
                              ),
                            ),
                          );
                        },
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        );
      }
    
      Stream<int> getStream()async*{
    
        for(int i = 0 ; i < 10 ; i++)
        yield i;
      }
    }
    

    Hope it helps you.