maxim-saplin / data_table_2

In-place substitute for Flutter's DataTable and PaginatedDataTable with fixed/sticky header and extra features
https://pub.dev/packages/data_table_2
BSD 3-Clause "New" or "Revised" License
202 stars 135 forks source link

DataRow2 color does not change when MaterialState is changing (mouse hover, pressed) #247

Closed fvisticot closed 8 months ago

fvisticot commented 8 months ago

I'm using a PaginatedDataTable2 with DataRow2 in a WEB APP I would like to change Row background color regarding mouse state (hover, pressed) I have added a log and the state is empty (so in my case color is always blue)

In the DataGrid Demo on the WEB, I see the mouse icon is changing when clicking on a Row and the Row color is changing.

In my case, the mouse cursor does not change when the mouse is inside the dataTable

return DataRow2(
      color: MaterialStateProperty.resolveWith<Color>((states) {
        print("State: $states");
        if (states.contains(MaterialState.pressed)) {
          return Color.fromRGBO(219, 250, 106, 1);
        }
        if (states.contains(MaterialState.hovered)) {
          return Colors.red;
        }
        return Colors.blue;
      }),
maxim-saplin commented 8 months ago

Please provide minimal repro example

fvisticot commented 8 months ago

Following a basic sample. When running for the WEB, Rows are always blue and mouse cursor does not change.

import 'package:data_table_2/data_table_2.dart';
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: PaginatedDataTable2(
          dataRowHeight: 60,
          columns: const [
            DataColumn2(label: Text('Col1')),
            DataColumn2(label: Text('Col2'))
          ],
          source: SampleDataSource(),
        ));
  }
}

class SampleDataSource extends DataTableSource {
  @override
  DataRow? getRow(int index) {
    return DataRow2(
        color: MaterialStateProperty.resolveWith<Color>((states) {
          if (states.contains(MaterialState.pressed)) {
            return const Color.fromRGBO(219, 250, 106, 1);
          }
          if (states.contains(MaterialState.hovered)) {
            return Colors.red;
          }
          return Colors.blue;
        }),
        cells: const [
          DataCell(Text("1")),
          DataCell(Text("2")),
        ]);
  }

  @override
  bool get isRowCountApproximate => false;

  @override
  int get rowCount => 10;

  @override
  int get selectedRowCount => 0;
}
maxim-saplin commented 8 months ago

You should have any tap events for the rows to start responding to mouse events (and trigger material state changes) + you should not return any default color (not sure why, that's the standard behaviour of the underlying InkWell).

import 'package:data_table_2/data_table_2.dart';
import 'package:flutter/material.dart';

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

  @override
  State<DataTable2SimpleDemo> createState() => _DataTable2SimpleDemoState();
}

class _DataTable2SimpleDemoState extends State<DataTable2SimpleDemo> {
  @override
  Widget build(BuildContext context) {
    return ColoredBox(
        color: Colors.yellow,
        child: PaginatedDataTable2(
          dataRowHeight: 60,
          wrapInCard: false,
          columns: const [
            DataColumn2(label: Text('Col1')),
            DataColumn2(label: Text('Col2'))
          ],
          source: SampleDataSource(),
        ));
  }
}

class SampleDataSource extends DataTableSource {
  @override
  DataRow2? getRow(int index) {
    return DataRow2(
        onTap: () {},
        color: MaterialStateProperty.resolveWith<Color?>((states) {
          if (states.contains(MaterialState.pressed)) {
            return const Color.fromRGBO(219, 250, 106, 1);
          } else if (states.contains(MaterialState.hovered)) {
            return Colors.red;
          }
          return null;
        }),
        cells: const [
          DataCell(Text("1")),
          DataCell(Text("2")),
        ]);
  }

  @override
  bool get isRowCountApproximate => false;

  @override
  int get rowCount => 10;

  @override
  int get selectedRowCount => 0;
}
image
fvisticot commented 8 months ago

Tx you for you quick answer and the great support. it works on my side too.

I still need to have the "row hover" feature working with the rounded corner rows. How to mix those 2 features ?

Adding the decoration property with ShapeBorder + color property regarding state give the following result :

image
maxim-saplin commented 8 months ago

I don't think you can achieve rounded corners on the hover effect using current widget. The best you can do is use row decoration with rounded corners and semi-transparent color and rectangular hover color behind.

It might be reasonable for you to go with the route of creating a custom widget controlling the looks of widgets

fvisticot commented 8 months ago

Did you mean I need to create my own DataTable widget to fully implement the requested design ? (It was my next idea :))

maxim-saplin commented 8 months ago

Create a custom layout with widgets that create the desired look, it doesn't have to be DataTable