Skip to content

[DataTable] Unable to center the label of a DataColumn without side effects #143340

@wer-mathurin

Description

@wer-mathurin

Steps to reproduce

Use the provided code to see the outcome.
As you will see, the label of the first column is not center.

After inspecting the source code this is cause by:

 label = Row(   <==============
      textDirection: numeric ? TextDirection.rtl : null,
      children: <Widget>[
        label, 
        if (onSort != null)
          ...<Widget>[
            _SortArrow(
              visible: sorted,
              up: sorted ? ascending : null,
              duration: _sortArrowAnimationDuration,
            ),
            const SizedBox(width: _sortArrowPadding),
          ],
      ],
    );

The label place inside a row, so the Center or Align have no effect.
But the simple solution like wrapping the label in a Flexible and a side effect of moving the sort arrow to the end of the cell...

So there is not easy solution(from my perspective) by not breaking the API of DataColumn.
One possible solution can be:

 label = Row(
      textDirection: numeric ? TextDirection.rtl : null,
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Flexible(child: label),
        if (onSort != null) ...<Widget>[
          customArrows ??
              _SortArrow(
                visible: sorted,
                up: sorted ? ascending : null,
                duration: sortArrowAnimationDuration,
                sortArrowIcon: sortArrowIcon,
              ),
          const SizedBox(width: _sortArrowPadding)
        ]
      ],
    );

    label = isCentered
        ? Row(
            textDirection: numeric ? TextDirection.rtl : null,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              if (onSort != null) ...<Widget>[
                const SizedBox(width: _sortArrowPadding),
                const SizedBox(width: _SortArrowState._arrowIconSize),
              ],
              Flexible(child: label),
            ],
          )
        : label;

But probably passing an Alignment can do the trick as well and be more generic. This is not perfect, but at least there will be a way to center the heading cell, and this is better than now :-)

Expected results

When using a Center or Align(center) widget in the heading cell, have the cell...center :-)
Or another mechanism to make it happen.

Actual results

The widget is not center in the heading cell.

Code sample

Code sample
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 const MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

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

class _MyHomePageState extends State<MyHomePage> {
  final source = _Source(items: Data.data);

  @override
  Widget build(BuildContext context) {
    final themeData = Theme.of(context).copyWith(
        dataTableTheme: const DataTableThemeData(
      columnSpacing: 0,
      horizontalMargin: 0,
      dividerThickness: 0,
      checkboxHorizontalMargin: 0,
    ));

    return Theme(
      data: themeData,
      child: PaginatedDataTable(
        columns: [
          DataColumn(
            label: const Center(
              child: Text(
                'Centered',
                textAlign: TextAlign.center,
              ),
            ),
            // numeric: true,
            onSort: (columnIndex, ascending) => setState(() {
              source.sort(ascending);
            }),
          ),
          const DataColumn(
            label: Text(
              'Second',
              textAlign: TextAlign.center,
            ),
          ),
        ],
        sortColumnIndex: 0,
        sortAscending: source.ascending,
        source: source,
      ),
    );
  }
}

class Data {
  static List<String> get data => List.generate(100, (index) => '$index');
}

class _Source extends DataTableSource {
  _Source({
    required this.items,
  });

  final List<String> items;
  bool ascending = false;

  @override
  DataRow? getRow(int index) {
    return DataRow.byIndex(index: index, cells: [
      DataCell(Center(child: Text(items[index]))),
      DataCell(Text(items[index])),
    ]);
  }

  void sort(bool ascending) {
    this.ascending = ascending;

    items.sort((a, b) => ascending ? a.compareTo(b) : b.compareTo(a));
    notifyListeners();
  }

  @override
  bool get isRowCountApproximate => false;

  @override
  int get rowCount => items.length;

  @override
  int get selectedRowCount => 0;
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.16.9, on macOS 14.2.1 23C71 darwin-arm64, locale en-CA)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2023.1)
[✓] VS Code (version 1.86.1)
[✓] Connected device (2 available)
[✓] Network resources

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listf: material designflutter/packages/flutter/material repository.found in release: 3.16Found to occur in 3.16found in release: 3.20Found to occur in 3.20frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-designOwned by Design Languages teamtriaged-designTriaged by Design Languages team

Type

No type

Projects

Status

Done (PR merged)

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions