add structure
This commit is contained in:
254
lib/reports/fixed_header.dart
Normal file
254
lib/reports/fixed_header.dart
Normal file
@@ -0,0 +1,254 @@
|
||||
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(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user