Home > Net >  How to lay out Rows and Columns in Flutter widget
How to lay out Rows and Columns in Flutter widget

Time:11-24

I am trying to build the UI for a simple screen with a few Text and TextBoxes but I am getting weird layout errors like this.

Error: Cannot hit test a render box that has never been laid out.
The hitTest() method was called on this RenderBox: RenderStack#487f4 NEEDS-LAYOUT NEEDS-PAINT:
  creator: Stack ← _FloatingActionButtonTransition ← MediaQuery ← LayoutId-[<_ScaffoldSlot.floatingActionButton>] ← CustomMultiChildLayout ← AnimatedBuilder ← DefaultTextStyle ← AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#0cc7b ink renderer] ← NotificationListener<LayoutChangedNotification> ← PhysicalModel ← AnimatedPhysicalModel ← ⋯
  parentData: offset=Offset(0.0, 0.0); id=_ScaffoldSlot.floatingActionButton
  constraints: MISSING
  size: MISSING
  alignment: Alignment.centerRight
  textDirection: ltr
  fit: loose
Unfortunately, this object's geometry is not known at this time, probably because it has never been laid out. This means it cannot be accurately hit-tested.
If you are trying to perform a hit test during the layout phase itself, make sure you only hit test nodes that have completed layout (e.g. the node's children, after their layout() method has been called).
    at Object.throw_ [as throw] (http://localhost:61969/dart_sdk.js:5061:11)
    at http://localhost:61969/packages/flutter/src/rendering/layer.dart.lib.js:4204:23
    at stack.RenderStack.new.hitTest (http://localhost:61969/packages/flutter/src/rendering/layer.dart.lib.js:4209:26)
    at http://localhost:61969/packages/flutter/src/rendering/layer.dart.lib.js:7665:44
    at box.BoxHitTestResult.wrap.addWithPaintOffset (http://localhost:61969/packages/flutter/src/rendering/layer.dart.lib.js:7418:19)
...

So, I removed all code and kept only two text boxes and two text fields to understand what is causing the problem. But I still can't figure out the reason. Here is my simplified code for the build method of my stateless widget:

@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
    appBar: AppBar(
      backgroundColor: Colors.red,
      title: Text("Create"),
    ),
    body: Container(
        child:Column(
            children: [
              //First row - Amount and Ccy labels/text boxes
              Expanded(
                  child: Row(
                    children: [
                      Expanded(
                          child:Column(
                            mainAxisSize: MainAxisSize.max,
                            children: [
                              Text('Amount'),
                              TextField(),
                            ],
                          )
                      ),
                      Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          Text('Currency'),
                          TextField(),
                        ],
                      )
                    ],
                  )
              ),
              //Second Row - Comment label/text box
            ]
        )
    )
);

}

I wonder if is some basic concept that I am missing here. I am testing it on Chrome.

CodePudding user response:

If you use TextField inside SizedBox with the determined height it might works

CodePudding user response:

After putting code i don't have this problem. is this UI the thing you wanted to achieve? how it looks


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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: "title",
        theme: ThemeData(primarySwatch: Colors.green),
        home: Scaffold(
          appBar: AppBar(
            backgroundColor: Colors.red,
            title: const Text("Create"),
          ),
          body: Container(
              child: Column(children: [
            //First row - Amount and Ccy labels/text boxes

            Row(children: [
              Expanded(
                  child: Column(
                mainAxisSize: MainAxisSize.max,
                children: const [
                  Text('Amount'),
                  TextField(),
                ],
              )),
              Column(
                mainAxisSize: MainAxisSize.min,
                children: const [
                  Text('Currency'),
               
                ],
              )
              //Second Row - Comment label/text box
            ])
          ])),
        ));
  }
}

CodePudding user response:

I think I found the answer to the issue. When I put two textfields in a row, with the first one in an Expanded widget, flutter isn't able to compute the right width to assign for the second one because TextFields don't have any width of their own unlike Text. So, its parent has to provide a width or flutter has to have something idea about what width to give it to that TextField. When I put both the textfields in Expanded of their own and assign a flex value to each, it works fine. Like this:

Expanded(
  flex:3, //this column is thrice as wide as the second one
  child: Column(
    mainAxisSize: MainAxisSize.max,
    children: const [
      Text('Amount'),
      TextField(),
    ],
  )),

Expanded(
    flex: 1, 
    child:Column(
    mainAxisSize: MainAxisSize.min,
    children: const [
      Text('Currency'),
      TextField(),
      ],
    )
)

I hope this is it.

  • Related