255 lines
7.4 KiB
Dart
255 lines
7.4 KiB
Dart
|
|
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<ReportsDataTable2> {
|
||
|
|
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<T> extends StatefulWidget {
|
||
|
|
final T fixedCornerCell;
|
||
|
|
final List<T> fixedColCells;
|
||
|
|
final List<T> fixedRowCells;
|
||
|
|
final List<List<T>> 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<StatefulWidget> createState() => CustomDataTableState();
|
||
|
|
}
|
||
|
|
|
||
|
|
class CustomDataTableState<T> extends State<CustomDataTable<T>> {
|
||
|
|
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: <Widget>[
|
||
|
|
Row(
|
||
|
|
children: <Widget>[
|
||
|
|
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: <Widget>[
|
||
|
|
_buildCornerCell(),
|
||
|
|
Flexible(
|
||
|
|
child: SingleChildScrollView(
|
||
|
|
controller: _rowController,
|
||
|
|
scrollDirection: Axis.horizontal,
|
||
|
|
physics: NeverScrollableScrollPhysics(),
|
||
|
|
child: _buildFixedRow(),
|
||
|
|
),
|
||
|
|
),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
],
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|