Search code examples
flutterdartdatatablecolorsdatatables

Flutter how to highlight multiple data rows on hover?


Background: I am currently working on a sticky data table, currently I have two DataTable widget in a Row as shown by the code below.

                    ...Row(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        // produce left rows
                        if (fixedLeftColumns > 0)
                          Container(
                            decoration: BoxDecoration(
                                color: Styles.defaultLightWhiteColor,
                                boxShadow: [Styles.defaultBoxShadow]),
                            child: DataTable(
                              showCheckboxColumn: false,
                              dividerThickness: 0.5,
                              columns: leftFixedHeaders
                                  .map((e) => DataColumn(
                                        onSort: e.onSort,
                                        tooltip:
                                            e.onSort == null ? null : e.label,
                                        label: Container(
                                            alignment: Alignment.centerLeft,
                                            height: rowHeight,
                                            width: e.width - 10,
                                            child: CustomText(text: e.label)),
                                      ))
                                  .toList(),
                              rows: [...leftFixedRows.map((e) => e)],
                            ),
                          ),
                        // produce table rows
                        Expanded(
                            child: SingleChildScrollView(
                          scrollDirection: Axis.horizontal,
                          controller: dataScrollController,
                          child: DataTable(
                            showCheckboxColumn: false,
                            dividerThickness: 0.5,
                            columns: centerFixedHeaders
                                .map((e) => DataColumn(
                                      onSort: e.onSort,
                                      tooltip:
                                          e.onSort == null ? null : e.label,
                                      label: Container(
                                          alignment: Alignment.centerLeft,
                                          height: rowHeight,
                                          width: e.width,
                                          child: CustomText(text: e.label)),
                                    ))
                                .toList(),
                            rows: [...centerFixedRows.map((e) => e)],
                          ),
                        )),
                      ],
                    ),
                  )

The sticky data table works quite well here, however I encountered a problem with this setup. When I hover into a row of the sticky table, it only highlights the row of the sticky table, however, I would like for the center table also to be highlighted on hovered or pressed.

Currently (cursor hovering the sticky table):

Current display

Expectations:

enter image description here

Is there any way to link both table rows to update simultaneously by hovering one? Or are there any other alternatives to produce this result?


Solution

  • I managed to find a workaround to produce hovering the whole row when on DataTable side by side by using MouseRegion.

    Using MouseRegion

    First I added the MouseRegion widget inside my DataCell and a new variable isHoveredIndex. When a movement of onEnter was found, set the to the index of the cell row isHoveredIndex = index. Clear the variable onExit to stop highlighting.

    I also needed to set the columnSpacing and horizontalMargin of DataTable to 0 and replace these spacing and margin manually in the DataCell, added with Column and Row so the MouseRegion's size will expand to the whole cell instead of just fitting a text's size.

    ...DataTable(
         showCheckboxColumn: false,
         horizontalMargin: 0,
         columnSpacing: 0,
         dividerThickness: 0.5,
         ...
    
    int? isHoveredIndex;
    
               ...DataCell(MouseRegion(
                    onEnter: (_) {
                      setState(() {
                        isHoveredIndex = index;
                      });
                    },
                    onExit: (event) {
                      setState(() {
                        isHoveredIndex = null;
                      });
                    },
                    child: Container(
                      padding: EdgeInsets.only(
                          left:
                              leftRow.first == e ? horizontalMargin : columnSpacing,
                          right:
                              leftRow.last == e ? horizontalMargin : columnSpacing),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Row(
                            children: [
                              e.child,
                            ],
                          ),
                        ],
                      ),
                    ),
                  ))
    
        ...DataRow(
              ...
              color: isHoveredIndex == index
                  ? WidgetStateProperty.all(
                      Colors.grey.withOpacity(0.2))
                  : null