import 'package:fcs/vo/report.dart'; import 'package:flutter/material.dart'; class ReportsDataTable2 extends StatefulWidget { Report report; ReportsDataTable2({this.report}); @override _ReportsDataTable2State createState() => _ReportsDataTable2State(); } class _ReportsDataTable2State extends State { final _rowsCells = [ [1, 8, 10, 8, 7], [2, 10, 9, 6, 6], [3, 4, 5, 7, 5], [4, 4, 1, 7, 8], [7, 8, 10, 8, 7], [10, 10, 9, 6, 6], [5, 4, 5, 7, 5], [9, 4, 1, 7, 8], [7, 8, 10, 8, 7], [10, 10, 9, 6, 6], [5, 4, 5, 7, 5], [9, 4, 1, 7, 8], [7, 8, 10, 8, 7], [10, 10, 9, 6, 6], [5, 4, 5, 7, 5], [9, 4, 1, 7, 8] ]; final _fixedColCells = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16" ]; final _fixedRowCells = [ "Math", "Informatics", "Geography", "Physics", "Biology" ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: CustomDataTable( rowsCells: _rowsCells, fixedColCells: _fixedColCells, fixedRowCells: _fixedRowCells, cellBuilder: (data) { return Container( decoration: BoxDecoration(border: Border.all(color: Colors.grey[400])), alignment: Alignment.centerRight, child: Text('$data')); }, fixedCornerCell: "", fixedColWidth: 20, cellWidth: 150, ), ); } } class CustomDataTable extends StatefulWidget { final T fixedCornerCell; final List fixedColCells; final List fixedRowCells; final List> rowsCells; final Widget Function(T data) cellBuilder; final double fixedColWidth; final double cellWidth; final double cellHeight; final double cellMargin; final double cellSpacing; CustomDataTable({ this.fixedCornerCell, this.fixedColCells, this.fixedRowCells, @required this.rowsCells, this.cellBuilder, this.fixedColWidth = 60.0, this.cellHeight = 56.0, this.cellWidth = 120.0, this.cellMargin = 0.0, this.cellSpacing = 0, }); @override State createState() => CustomDataTableState(); } class CustomDataTableState extends State> { final _columnController = ScrollController(); final _rowController = ScrollController(); final _subTableYController = ScrollController(); final _subTableXController = ScrollController(); Widget _buildChild(double width, T data) => SizedBox( width: width, child: widget.cellBuilder?.call(data) ?? Text('$data')); Widget _buildHeader(double width, T data) => SizedBox( width: width, child: Container( decoration: BoxDecoration(border: Border.all(color: Colors.grey[400])), alignment: Alignment.centerRight, child: Text('$data'))); Widget _buildFixedCol() => widget.fixedColCells == null ? SizedBox.shrink() : Material( color: Colors.grey[300], child: DataTable( horizontalMargin: widget.cellMargin, columnSpacing: widget.cellSpacing, headingRowHeight: widget.cellHeight, dataRowHeight: widget.cellHeight, columns: [ DataColumn( label: _buildChild( widget.fixedColWidth, widget.fixedColCells.first), numeric: true) ], rows: widget.fixedColCells .sublist(widget.fixedRowCells == null ? 1 : 0) .map((c) => DataRow( cells: [DataCell(_buildChild(widget.fixedColWidth, c))])) .toList()), ); Widget _buildFixedRow() => widget.fixedRowCells == null ? SizedBox.shrink() : Material( color: Colors.grey[300], child: Theme( data: Theme.of(context).copyWith(dividerColor: Colors.green), child: DataTable( horizontalMargin: widget.cellMargin, columnSpacing: widget.cellSpacing, headingRowHeight: widget.cellHeight, dataRowHeight: widget.cellHeight, columns: widget.fixedRowCells .map((c) => DataColumn(label: _buildHeader(widget.cellWidth, c))) .toList(), rows: []), ), ); Widget _buildSubTable() => Material( child: DataTable( horizontalMargin: widget.cellMargin, columnSpacing: widget.cellSpacing, headingRowHeight: widget.cellHeight, dataRowHeight: widget.cellHeight, // MyDataRowHeight: widget.cellHeight, columns: widget.rowsCells.first .map((c) => DataColumn( label: _buildChild(widget.cellWidth, c), numeric: true)) .toList(), rows: widget.rowsCells .sublist(widget.fixedRowCells == null ? 1 : 0) .map((row) => DataRow( cells: row .map((c) => DataCell(_buildChild(widget.cellWidth, c))) .toList())) .toList())); Widget _buildCornerCell() => widget.fixedColCells == null || widget.fixedRowCells == null ? SizedBox.shrink() : Material( color: Colors.grey[300], child: DataTable( horizontalMargin: widget.cellMargin, columnSpacing: widget.cellSpacing, headingRowHeight: widget.cellHeight, dataRowHeight: widget.cellHeight, columns: [ DataColumn( label: _buildChild( widget.fixedColWidth, widget.fixedCornerCell)) ], rows: []), ); @override void initState() { super.initState(); _subTableXController.addListener(() { _rowController.jumpTo(_subTableXController.position.pixels); }); _subTableYController.addListener(() { _columnController.jumpTo(_subTableYController.position.pixels); }); } @override Widget build(BuildContext context) { return Stack( children: [ Row( children: [ SingleChildScrollView( controller: _columnController, scrollDirection: Axis.vertical, physics: NeverScrollableScrollPhysics(), child: _buildFixedCol(), ), Flexible( child: SingleChildScrollView( controller: _subTableXController, scrollDirection: Axis.horizontal, child: SingleChildScrollView( controller: _subTableYController, scrollDirection: Axis.vertical, child: _buildSubTable(), ), ), ), ], ), Row( children: [ _buildCornerCell(), Flexible( child: SingleChildScrollView( controller: _rowController, scrollDirection: Axis.horizontal, physics: NeverScrollableScrollPhysics(), child: _buildFixedRow(), ), ), ], ), ], ); } }