flutter PaginatedDataTable rowsPerPage 可以设置为不能被 10 整除的数字吗?
更新
FutureBuilder 使用的数据是从本地服务器获取的。起初,该列表包含 3 个项目,这会导致创建空的 DataRow。
我的问题
我试过的东西
示例代码
import 'package:flutter/material.dart';
import 'package:nvip/constants.dart';
import 'package:nvip/data_repo/network/centers_repo.dart';
import 'package:nvip/data_repo/tables/data_source_centers.dart';
import 'package:nvip/models/vaccination_center.dart';
class VaccinationCentersTableScreen extends StatelessWidget {
@override
Widget build(BuildContext context) => _CentersScreenBody();
}
class _CentersScreenBody extends StatefulWidget {
@override
__CentersScreenBodyState createState() => __CentersScreenBodyState();
}
class __CentersScreenBodyState extends State<_CentersScreenBody> {
int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage; // This one works
int _columnIndex = 1;
bool _isSortAscending = true;
Future<List<VaccineCenter>> _centers;
CentersTableDataSource _tableDataSource;
var _scaffoldKey = GlobalKey<ScaffoldState>();
void _sort<T>(Comparable<T> getField(VaccineCenter c), int columnIndex,
bool isSortAscending) {
_tableDataSource?.sort(getField, isSortAscending);
setState(() {
_columnIndex = columnIndex;
_isSortAscending = isSortAscending;
});
}
@override
void initState() {
super.initState();
_centers = VaccineCentersDataRepo().getCenters();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
Navigator.pushReplacementNamed(context, Routes.keyHome);
},
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("Vaccination Centers"),
centerTitle: true,
leading: IconButton(
icon: Icon(Constants.backIcon),
onPressed: () {
Navigator.pushReplacementNamed(context, Routes.keyHome);
},
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
tooltip: "Add vaccination center",
onPressed: () {
Navigator.pushReplacementNamed(context, Routes.keyPovAdd);
},
)
],
),
body: FutureBuilder<List<VaccineCenter>>(
future: _centers,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Constants.showHasNoDataWidget(
context,
"No vaccination center(s) / place(s) of vaccinations found. "
"Press the (+) sign to add a new record.",
);
} else {
if (snapshot.hasData) {
var centerList = snapshot.data;
var centersCount = centerList.length;
var defaultRowsPerPage = PaginatedDataTable.defaultRowsPerPage;
_rowsPerPage = centersCount < defaultRowsPerPage
? centersCount
: defaultRowsPerPage;
_tableDataSource = CentersTableDataSource(centerList);
return SingleChildScrollView(
child: PaginatedDataTable(
header: Text("Places of Vaccination"),
rowsPerPage: _rowsPerPage,
onRowsPerPageChanged: (rowCount) {
setState(() {
_rowsPerPage = rowCount;
});
},
sortColumnIndex: _columnIndex,
sortAscending: _isSortAscending,
onSelectAll: (isAllChecked) =>
_tableDataSource?.selectAll(isAllChecked),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
tooltip: "Add vaccination center",
onPressed: () {
Navigator.pushReplacementNamed(
context, Routes.keyPovAdd);
},
),
IconButton(
icon: Icon(Icons.delete_forever),
tooltip: "Delete vaccination center(s).",
onPressed: () {
Constants.showSnackBar(
_scaffoldKey, "Delete button clicked");
},
)
],
columns: <DataColumn>[
DataColumn(
label: Text("No."),
numeric: true,
onSort: (ci, isSortAscending) => _sort<num>(
(c) => centerList.indexOf(c), ci, isSortAscending),
),
DataColumn(
label: Text("Name"),
onSort: (ci, isSortAscending) =>
_sort<String>((c) => c.name, ci, isSortAscending),
),
],
source: _tableDataSource,
),
);
}
}
return Center(child: CircularProgressIndicator());
},
),
),
);
}
}
错误日志
I/flutter ( 8474): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 8474): The following assertion was thrown building FutureBuilder<List<VaccineCenter>>(dirty, state:
I/flutter ( 8474): _FutureBuilderState<List<VaccineCenter>>#92379):
I/flutter ( 8474): 'package:flutter/src/material/paginated_data_table.dart': Failed assertion: line 87 pos 19:
I/flutter ( 8474): 'availableRowsPerPage != null && availableRowsPerPage.contains(rowsPerPage)': is not true.
I/flutter ( 8474):
I/flutter ( 8474): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter ( 8474): more information in this error message to help you determine and fix the underlying cause.
I/flutter ( 8474): In either case, please report this assertion by filing a bug on GitHub:
I/flutter ( 8474): https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter ( 8474):
I/flutter ( 8474): When the exception was thrown, this was the stack:
I/flutter ( 8474): #2 new PaginatedDataTable.<anonymous closure> (package:flutter/src/material/paginated_data_table.dart:87:19)
I/flutter ( 8474): #3 new PaginatedDataTable (package:flutter/src/material/paginated_data_table.dart:89:9)
I/flutter ( 8474): #4 __CentersScreenBodyState.build.<anonymous closure> (package:nvip/scenes/vaccination_centers/screen_center_table.dart:86:26)
I/flutter ( 8474): #5 _FutureBuilderState.build (package:flutter/src/widgets/async.dart)
I/flutter ( 8474): #6 StatefulElement.build (package:flutter/src/widgets/framework.dart:3809:27)
I/flutter ( 8474): #7 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3721:15)
I/flutter ( 8474): #8 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
I/flutter ( 8474): #9 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2286:33)
I/flutter ( 8474): #10 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:676:20)
I/flutter ( 8474): #11 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5)
I/flutter ( 8474): #12 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
I/flutter ( 8474): #13 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
I/flutter ( 8474): #14 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
I/flutter ( 8474): #15 _invoke (dart:ui/hooks.dart:154:13)
I/flutter ( 8474): #16 _drawFrame (dart:ui/hooks.dart:143:3)
I/flutter ( 8474): (elided 2 frames from class _AssertionError)
I/flutter ( 8474): ════════════════════════════════════════════════════════════════════════════════════════════════════
更新 2
我的数据表源
import 'package:flutter/material.dart';
import 'package:nvip/models/vaccination_center.dart';
class CentersTableDataSource extends DataTableSource {
final List<VaccineCenter> _centers;
int _rowsSelectedCount = 0;
CentersTableDataSource(this._centers);
@override
DataRow getRow(int index) {
assert(index >= 0);
if (index >= _centers.length) return null;
final VaccineCenter center = _centers[index];
return DataRow.byIndex(
index: index,
selected: center.isSelected,
onSelectChanged: (selected) {
if (center.isSelected != selected) {
_rowsSelectedCount += selected ? 1 : -1;
center.isSelected = selected;
notifyListeners();
}
},
cells: <DataCell>[
DataCell(Text("${index + 1}")),
DataCell(Text(center.name)),
],
);
}
@override
bool get isRowCountApproximate => false;
@override
int get rowCount => _centers.length;
@override
int get selectedRowCount => _rowsSelectedCount;
void sort<T extends Object>(
Comparable<T> getField(VaccineCenter d), bool isAscending) {
_centers.sort((a, b) {
if (isAscending) {
final VaccineCenter c = a;
a = b;
b = c;
}
final Comparable<T> aValue = getField(a);
final Comparable<T> bValue = getField(b);
return Comparable.compare(aValue, bValue);
});
notifyListeners();
}
void selectAll(bool isAllChecked) {
_centers.forEach((center) => center.isSelected = isAllChecked);
_rowsSelectedCount = isAllChecked ? _centers.length : 0;
notifyListeners();
}
}
最佳答案
import 'package:flutter/material.dart';
class DemoTable extends StatelessWidget {
@override
Widget build(BuildContext context) {
return _DemoTableBody();
}
}
class _DemoTableBody extends StatefulWidget {
@override
__DemoTableBodyState createState() => __DemoTableBodyState();
}
class __DemoTableBodyState extends State<_DemoTableBody> {
int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;
// A Variable to hold the length of table based on the condition of comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage
int _rowsPerPage1 = PaginatedDataTable.defaultRowsPerPage;
@override
Widget build(BuildContext context) {
//Obtain the data to be displayed from the Derived DataTableSource
var dts = DTS();
// dts.rowcount provides the actual data length, ForInstance, If we have 7 data stored in the DataTableSource Object, then we will get 12 as dts.rowCount
var tableItemsCount = dts.rowCount;
// PaginatedDataTable.defaultRowsPerPage provides value as 10
var defaultRowsPerPage = PaginatedDataTable.defaultRowsPerPage;
// We are checking whether tablesItemCount is less than the defaultRowsPerPage which means we are actually checking the length of the data in DataTableSource with default PaginatedDataTable.defaultRowsPerPage i.e, 10
var isRowCountLessDefaultRowsPerPage = tableItemsCount < defaultRowsPerPage;
// Assigning rowsPerPage as 10 or acutal length of our data in stored in the DataTableSource Object
_rowsPerPage =
isRowCountLessDefaultRowsPerPage ? tableItemsCount : defaultRowsPerPage;
return Scaffold(
appBar: AppBar(
title: Text("Demo Paginated Table"),
),
body: SingleChildScrollView(
child: PaginatedDataTable(
header: Text('data with 7 rows per page'),
// comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage and then assigning it to _rowPerPage1 variable which then set using the setsState()
onRowsPerPageChanged: isRowCountLessDefaultRowsPerPage // The source of problem!
? null
: (rowCount) {
setState(() {
_rowsPerPage1 = rowCount;
});
},
columns: <DataColumn>[
DataColumn(label: Text('row')),
DataColumn(label: Text('name')),
],
source: dts,
//Set Value for rowsPerPage based on comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage
rowsPerPage:
isRowCountLessDefaultRowsPerPage ? _rowsPerPage : _rowsPerPage1,
),
),
);
}
}
class DTS extends DataTableSource {
@override
DataRow getRow(int index) {
return DataRow.byIndex(
index: index,
cells: [
DataCell(Text('row #$index')),
DataCell(Text('name #$index')),
],
);
}
@override
int get rowCount => 9; // Manipulate this to which ever value you wish
@override
bool get isRowCountApproximate => false;
@override
int get selectedRowCount => 0;
}