I'm trying to build a full width DataTable in Flutter with a fixed width column on the left and two other columns which should divide the remaining with.

However, even if the left header text is truncated, the middle and right column don't take the remaining width, as you can see below:

Table screenshot

I would also like to wrap the text in a cell when it is too wide to be displayed in a single row, but Wrap is not working as expected.

How can i solve my issues?

Here's the code:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Column(children: [
          Expanded(
            child: Container(
              constraints: BoxConstraints.expand(width: double.infinity),
              child: SingleChildScrollView(
                child: DataTable(
                    headingRowHeight: 32,
                    dataRowHeight: 24,
                    columns: [
                      DataColumn(
                        label: ConstrainedBox(
                          constraints: BoxConstraints(
                            maxWidth: 20,
                            minWidth: 20,
                          ),
                          child: Text('Short column'),
                        ),
                      ),
                      DataColumn(label: Text('Long column')),
                      DataColumn(label: Text('Long column')),
                    ],
                    rows: [
                      DataRow(
                        cells: [
                          DataCell(
                            ConstrainedBox(
                              constraints: BoxConstraints(
                                maxWidth: 20,
                                minWidth: 20,
                              ),
                              child: Text('1'),
                            ),
                          ),
                          DataCell(
                            Wrap(
                              children: [
                                Text(
                                    """Some long content i would like to be wrapped when column width is not
                              enought to fully display it"""),
                              ],
                            ),
                          ),
                          DataCell(Text('Some more text')),
                        ],
                      ),
                      DataRow(
                        cells: [
                          DataCell(Container(
                            color: Colors.pink,
                            child: ConstrainedBox(
                              constraints: BoxConstraints(
                                maxWidth: 20,
                                minWidth: 20,
                              ),
                              child: Text('2'),
                            ),
                          )),
                          DataCell(
                            Wrap(
                              children: [
                                Container(
                                    color: Colors.yellow,
                                    child: Text(
                                        """Some long content i would like to be wrapped when column width is not
                              enought to fully display it""")),
                              ],
                            ),
                          ),
                          DataCell(Text('Some more text')),
                        ],
                      )
                    ]),
              ),
            ),
          ),
        ]),
      ),
    );
  }
}

EDIT

Thanks to @awaik for the answer, but in your example the table is not taking full device width, it remains in the middle with a large screen, which is not what i wanted.

Also, row height is constant, it does not increase if the content needs more height.

Is there anything that can be done?


Solution 1: awaik

the DataTable has some default values:

DataTable({
  Key key,
  @required this.columns,
  this.sortColumnIndex,
  this.sortAscending = true,
  this.onSelectAll,
  this.dataRowHeight = kMinInteractiveDimension,
  this.headingRowHeight = 56.0,
  this.horizontalMargin = 24.0,
  this.columnSpacing = 56.0,

Below the fixed example with some widgets deleted.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: DataTable(
            horizontalMargin: 6.0,
            columnSpacing: 6.0,
            headingRowHeight: 32.0,
            dataRowHeight: 100.0,
            columns: [
              DataColumn(
                label: ConstrainedBox(
                  constraints: BoxConstraints(
                    maxWidth: 20,
                    minWidth: 20,
                  ),
                  child: Text('Short column'),
                ),
              ),
              DataColumn(label: Text('Long column')),
              DataColumn(label: Text('Three')),
            ],
            rows: [
              DataRow(
                cells: [
                  DataCell(
                    Text('1'),
                  ),
                  DataCell(
                    Container(
                      child: Text(
                        'Some long content i would like to be wrapped ',
                      ),
                    ),
                  ),
                  DataCell(Text('Some more text')),
                ],
              ),
              DataRow(
                cells: [
                  DataCell(Container(
                    color: Colors.pink,
                    child: Text('2'),
                  )),
                  DataCell(
                      Container(
                        height: 500,
                        color: Colors.yellow,
                        child: Text(
                          'Some long content i would like to be wrapped when column width is not enought to fully display itSome long content i would like to be wrapped when column width is not display it Some long content i would like to be wrapped when column width is not enought to fully display itSome long content i would like to be wrapped when column width is not display it Some long content i would like to be wrapped when column width is not enought to fully display itSome long content i would like to be wrapped when column width is not display it 555',
                        ),
                      ),
                      placeholder: false),
                  DataCell(Text('Some more text')),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

EDIT

  1. The code upward has updated.
  2. The table wasn't taken full width, because we used multiline strings with tree """. If we use regular string, the behavior is normal.
  3. The height of the row is set in the constructor and couldn't be changed dynamically.

    child: DataTable( horizontalMargin: 6.0, columnSpacing: 6.0, headingRowHeight: 32.0, dataRowHeight: 100.0,

Finally, my personal point of view - it is easier to create your own widget instead using this DataTable

enter image description here


Solution 2: Ansharja

I found out that a normal Table allows me to do what i want: i can use FixedColumnWidth for a certain column and FlexColumnWidth for the others in order to take the remaining space.

Also, text is correctly wrapped and row height increases in order to fit the content, like in the image below with a small screen width and a large screen width:

enter image description here

And this is the code:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Column(children: [
          Expanded(
            child: Container(
              child: SingleChildScrollView(
                child: Table(
                  border: TableBorder.all(width: 1),
                  columnWidths: {
                    0: FixedColumnWidth(20),
                  },
                  defaultColumnWidth: FlexColumnWidth(),
                  children: [
                    TableRow(children: [
                      Text('Short column'),
                      Text('Long column'),
                      Text('Long column')
                    ]),
                    TableRow(
                      children: [
                        Text('1'),
                        Text(
                            'Some long content i would like to be wrapped when column width is not enought to fully display it'),
                        Container(
                          child: Text('Some more text'),
                        )
                      ],
                    )
                  ],
                ),
              ),
            ),
          ),
        ]),
      ),
    );
  }
}