How to make the Flutter DataTable header as sticky while its content is scrollable?

306 Views Asked by At

I am trying to make a flutter DataTable's header fixed while scrolling. I want only the content to scroll Scrolling behavior referenced from NG-Zorro Table.

enter image description here

I tried using table_sticky_headers. But is there any way to achieve this natively without using any package?

As I am using DataTable widget. i need the header(DataColumn) to be fixed, and the content(DataRow) should be scrollable, but i am not able to use the scrollable widget inside the cells. so i am using SingleChildScroolView outside the DataTable Widget.

I have attached the sample code below to work on.

import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 32),
      child: Card(
        margin: EdgeInsets.zero,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: SingleChildScrollView(
                padding: EdgeInsets.zero,
                child: SizedBox(
                  width: double.infinity,
                  child: CheckboxTheme(
                    data: CheckboxThemeData(
                      side: MaterialStateBorderSide.resolveWith(
                        (_) =>
                            const BorderSide(width: 1, color: Colors.blueGrey),
                      ),
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(5),
                      ),
                      fillColor: MaterialStateProperty.all(Colors.blueGrey[25]),
                      checkColor: MaterialStateProperty.all(
                        Colors.blueGrey[700],
                      ),
                    ),
                    child: DataTable(
                      columnSpacing: 12,
                      headingRowColor: MaterialStateProperty.resolveWith(
                          (states) => Colors.grey[50]),
                      dataRowHeight: 60,
                      checkboxHorizontalMargin: 5,
                      showCheckboxColumn: true,
                      horizontalMargin: 6,
                      columns: [
                        DataColumn(
                          label: Padding(
                            padding: const EdgeInsets.only(left: 20),
                            child: Text(
                              'header 1',
                              style: TextStyle(
                                fontSize: 12,
                                color: Colors.grey[500],
                                fontWeight: FontWeight.w500,
                              ),
                            ),
                          ),
                        ),
                        DataColumn(
                          label: Text(
                            'heder 2',
                            style: TextStyle(
                              fontSize: 12,
                              color: Colors.grey[500],
                              fontWeight: FontWeight.w500,
                            ),
                          ),
                        ),
                        DataColumn(
                          label: Text(
                            'header 3',
                            style: TextStyle(
                              fontSize: 12,
                              color: Colors.grey[500],
                              fontWeight: FontWeight.w500,
                            ),
                          ),
                        ),
                        DataColumn(
                          label: Expanded(
                            child: Text(
                              'header 4',
                              style: TextStyle(
                                fontSize: 12,
                                color: Colors.grey[500],
                                fontWeight: FontWeight.w500,
                              ),
                            ),
                          ),
                        ),
                      ],
                      rows: [
                        for (int x = 0; x < 20; x++)
                          DataRow(
                            color: MaterialStateProperty.resolveWith((states) {
                              if (states.contains(MaterialState.selected)) {
                                return Colors.transparent;
                              }
                              return Colors.transparent;
                            }),
                            cells: [
                              DataCell(
                                Padding(
                                  padding: const EdgeInsets.only(left: 20),
                                  child: Text(
                                    "data 1",
                                    style: TextStyle(
                                      fontSize: 14,
                                      color: Colors.grey[900],
                                      fontWeight: FontWeight.w500,
                                    ),
                                  ),
                                ),
                              ),
                              DataCell(
                                Text(
                                  "data 2",
                                  style: TextStyle(
                                    fontSize: 14,
                                    color: Colors.grey[900],
                                    fontWeight: FontWeight.w500,
                                  ),
                                ),
                              ),
                              DataCell(
                                Text(
                                  "data 3",
                                  style: TextStyle(
                                    fontSize: 14,
                                    color: Colors.grey[900],
                                    fontWeight: FontWeight.w500,
                                  ),
                                ),
                              ),
                              DataCell(
                                Text(
                                  "data 4",
                                  style: TextStyle(
                                    fontSize: 14,
                                    color: Colors.grey[900],
                                    fontWeight: FontWeight.w500,
                                  ),
                                ),
                              ),
                            ],
                          )
                      ],
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
1

There are 1 best solutions below

0
On

You can do it with DataTable2 , just install the package here is the link : https://pub.dev/packages/data_table_2 you just have to do minor changes like and then you have to use the property - fixedTopRows to fix the rows let's say you want to freezed the header or 1st row so put it like, Also DataTable2 provide you more add on features over the DataTable -

 DataTable2(
                  fixedColumnsColor: context
                      .utils.colorUtils.tableBorderColor
                      .withOpacity(0.2),
                  fixedTopRows: 1,
                  fixedCornerColor:
                      context.utils.colorUtils.tableBorderColor,
                  border: TableBorder(
                    top: BorderSide(
                        color: context.utils.colorUtils.tableBorderColor),
                    bottom: BorderSide(
                        color: context.utils.colorUtils.tableBorderColor),
                  ),
                  scrollController: ScrollController(),
                  fixedLeftColumns: 1,
                  headingRowDecoration: BoxDecoration(
                    color: context.utils.colorUtils.tableBorderColor,
                  ),
                  horizontalScrollController: ScrollController(),
                  minWidth: 456.w,
                  dividerThickness: 0.6,
                  horizontalMargin: 16.w,
                  dataTextStyle: poppinsRegular.copyWith(
                    fontSize: 12.sp,
                    color:Colors.black,
                  ),
                  headingRowHeight: context.height * 0.054,
                  dataRowHeight: context.height * 0.056,
                  headingTextStyle: poppinsMedium.copyWith(
                    fontSize: 12.sp,
                    color: context.utils.colorUtils.primaryTextColor,
                  ),
                  columns: [],
                  rows: [],
                ),