Axel
Axel

Reputation: 1475

How to build a flutter form with two columns and multiple rows?

I am trying to build a rather simple Flutter form that consists of three rows of which the first two rows each hold three columns. I therefore made a Form that holds a Padding as a child, while this Padding has a Column as a child, which finally contains the three rows:

  Widget build(BuildContext context) {
    // Build a Form widget using the _formKey created above.
    return Form(
      key: _formKey,
      child: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                TextFormField(
                  validator: (value) {
                    if (value.isEmpty) {
                      return 'Please enter place of departure';
                    }
                    return null;
                  },
                  controller: fromController,
                  decoration: InputDecoration(
                      border: InputBorder.none,
                      hintText: 'From'
                  ),
                ),
                RaisedButton(
                  onPressed: () => _selectDate(context),
                  child: Text('Select date'),
                ),
                RaisedButton(
                  onPressed: () => _selectTime(context),
                  child: Text('Select time'),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                TextFormField(
                  validator: (value) {
                    if (value.isEmpty) {
                      return 'Please enter destination';
                    }
                    return null;
                  },
                  controller: toController,
                  decoration: InputDecoration(
                      border: InputBorder.none,
                      hintText: 'To'
                  ),
                )
              ]
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                  RaisedButton(
                  onPressed: () {
                    // Validate returns true if the form is valid, or false
                    // otherwise.
                    if (_formKey.currentState.validate()) {
                      // If the form is valid, display a Snackbar.
                      Scaffold.of(context)
                          .showSnackBar(SnackBar(content: Text('You fly from '+fromController.text+' to '+toController.text)));
                    }
                  },
                  child: Text('Take off'),
                ),
              ]
            ),
          ],
        ),
      ),
    );
  }

Unfortunately this is not working this way and I can't figure out, how I need to structure the Form to build it successfully and leads to a render error. What I would like to build in the end would be something like this:

Desired layout

Upvotes: 1

Views: 4158

Answers (1)

Marc Sanny
Marc Sanny

Reputation: 1141

While wrapping rows into column there should be size specified, You can wrap your rows && children's with Flexible or Expanded, this worked for your example:

  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Flexible(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  Flexible(
                    child: TextFormField(
                      validator: (value) {
                        if (value.isEmpty) {
                          return 'Please enter place of departure';
                        }
                        return null;
                      },
                      controller: fromController,
                      decoration: InputDecoration(
                          border: InputBorder.none,
                          hintText: 'From'
                      ),
                    ),
                  ),
                  Flexible(
                    child: RaisedButton(
                      onPressed: () => _selectDate(context),
                      child: Text('Select date'),
                    ),
                  ),
                  Flexible(
                    child: RaisedButton(
                      onPressed: () => _selectTime(context),
                      child: Text('Select time'),
                    ),
                  ),
                ],
              ),
            ),
            Flexible(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  Flexible(
                    child: TextFormField(
                      validator: (value) {
                        if (value.isEmpty) {
                          return 'Please enter destination';
                        }
                        return null;
                      },
                      controller: toController,
                      decoration: InputDecoration(
                          border: InputBorder.none,
                          hintText: 'To'
                      ),
                    ),
                  )
                ]
              ),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                RaisedButton(
                  onPressed: () {
                    // Validate returns true if the form is valid, or false
                    // otherwise.
                    if (_formKey.currentState.validate()) {
                      // If the form is valid, display a Snackbar.
                      Scaffold.of(context)
                          .showSnackBar(SnackBar(content: Text('You fly from '+fromController.text+' to '+toController.text)));
                    }
                  },
                  child: Text('Take off'),
                ),
              ]
            ),
          ],
        ),
      ),
    );
  }

You might specify flex, work with expanded instead of flexibles & try some other mainAxisAlignment behaviours on your rows for the best effect, but in general it works pretty good

Upvotes: 3

Related Questions