skip to Main Content

In my codes, Row widget nested in Column widget are causing exception at times. I searched and found that you can nest Row in Column however. So, I am unable to find the cause and more importantly the fix of the exception.

My main code has the following layout as shown in the diagram below: (Here, if Column widget is replaced by Row widget, shown by marking tick and cross, an exception occurs, and I can’t figure out why and how to solve it!)

main_program_layout

Then, I tried with another program with the following layout:

example_program

In this example program, the first Row has two Text children and does not cause any error, unless we add more children or length of text sufficient to cause an overflow at the side edge. So, this cleared my doubt if it was possible to nest a Row in a Column: apparently we can.

Then I added another Row widget, which was fine until the content were Text with content short enough to fit horizontally, and then I replaced the Text child with a TextField which I need in my main layout as well, an exception occurred here as well.

What is the reason and how can I solve this? Below is the code of the second example layout:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late TextEditingController controller;
  String text = "";

  @override
  void initState() {
    super.initState();
    controller = TextEditingController();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  bool? _isChecked = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          children: [
            const Text("First child of Column."),
            const Column(
              children: [
                Text("First child of Column nested within another Column"),
                Text(
                    "Second child of Column nested within another Column; making this line longer did not cause overflow at the side edge."),
              ],
            ),
            // Using enough children or long text in Row may cause overflow
            const Row(
              children: [
                Text("Text01"),
                Text("Text02"),
                Text("Text03"),
              ],
            ),
            Row(
              children: [
                TextField(
                  controller: controller,
                  onSubmitted: (String value) {
                    setState(() {
                      text = controller.text;
                    });
                  },
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

UPDATE 01:

I tried wrapping inside Flexible and Expanded the entire Row and in other only the children (I need both TextField and CheckboxListTile in a row) of Row both in Flexible, but nothing worked. One of the code I tried:

        Expanded(
          child: Row(
            children: [
              TextField(
                controller: controller,
                onSubmitted: (String value) {
                  setState(() {
                    text = controller.text;
                  });
                },
              ),
              CheckboxListTile(
                value: _isChecked,
                controlAffinity: ListTileControlAffinity.leading,
                onChanged: (bool? newValue) {
                  setState(() {
                    _isChecked = newValue;
                    if (_isChecked == true) {
                      //text = "Default Value 01";
                      /*
                  controller =
                      TextEditingController(text: "Default Value 01");
                  */
                      controller.text = "Default Value 01";
                    }
                    if (_isChecked == false) {
                      //text = "";
                      /*
                  controller = TextEditingController(text: "");
                  */
                      controller.clear();
                    }
                  });
                },
                title: Text("Checkbox"),
              ),
            ],
          ),
        ),

3

Answers


  1. If you are worry about the overflow of long text in the row, you may let the text expand within the Row.

    Row(
    
    children:[
    
    Text('short'),
    
    Expanded(
    child: Text(
     'very long very long very long very long very long very long',
     // handle overflow also
      overflow: TextOverflow.ellipsis,
    
       )
      )
     ]
    ) 
    

    btw, you should wrap your entire column with SingleChildScrollView to handle the vertical overflow.

    Hope it helps you.

    Login or Signup to reply.
  2. You just need to wrap your TextField inside the Expanded or Flexible widget:

                Row(
                  children: [
                    Flexible(
                      child: TextField(
                        controller: controller,
                        onSubmitted: (String value) {
                          setState(() {
                            text = controller.text;
                          });
                        },
                      ),
                    ),
                  ],
                ),
    

    or if you are going to use only one item, like the TextField just remove the row and use the TextField directly.

    UPDATE:

    If you need the TextField and CheckboxListTile use this :

                  Row(
                    children: [
                      Expanded(
                        child: TextField(
                          controller: controller,
                          onSubmitted: (String value) {
                            setState(() {
                              text = controller.text;
                            });
                          },
                        ),
                      ),
                      Flexible(
                        child: CheckboxListTile(
                          value: _isChecked,
                          controlAffinity: ListTileControlAffinity.leading,
                          onChanged: (bool? newValue) {
                            setState(() {
                               _isChecked = newValue;
                              if (_isChecked == true) {
                                //text = "Default Value 01";
                                /*
                          controller =
                              TextEditingController(text: "Default Value 01");
                          */
                                controller.text = "Default Value 01";
                              }
                              if (_isChecked == false) {
                                //text = "";
                                /*
                          controller = TextEditingController(text: "");
                          */
                                controller.clear();
                              }
                            });
                          },
                          title: const Text("Checkbox"),
                        ),
                      ),
                    ],
                  ),
    
    Login or Signup to reply.
  3. If you’re encountering the error, you can resolve it by wrapping the TextField inside an Expanded or Flexible widget within the Row.

              Row(
                  children: [
                    TextField(
                      controller: controller,
                      onSubmitted: (String value) {
                        setState(() {
                          text = controller.text;
                        });
                      },
                    ),
                  ],
                )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search