Flutter表格多行编辑实现求助:参考DataTables示例求简便方案
Flutter 表格多行编辑的简便实现方案
方案一:使用成熟第三方包(推荐)
最简便的方式是借助功能完善的表格组件包,比如Syncfusion Flutter DataGrid,它原生支持多行选择、批量编辑,和你提到的Datatables示例逻辑匹配:
- 添加依赖
在pubspec.yaml中加入:
dependencies: syncfusion_flutter_datagrid: ^25.1.35 # 替换为最新版本
- 实现数据源与多行编辑逻辑
import 'package:syncfusion_flutter_datagrid/datagrid.dart'; // 定义数据模型 class Employee { Employee(this.id, this.name, this.designation, this.salary); final int id; String name; String designation; double salary; } // 自定义数据源 class EmployeeDataSource extends DataGridSource { EmployeeDataSource(List<Employee> employees) { _employees = employees .map<DataGridRow>((e) => DataGridRow(cells: [ DataGridCell<int>(columnName: 'id', value: e.id), DataGridCell<String>(columnName: 'name', value: e.name), DataGridCell<String>(columnName: 'designation', value: e.designation), DataGridCell<double>(columnName: 'salary', value: e.salary), ])) .toList(); } List<DataGridRow> _employees = []; List<DataGridRow> selectedRows = []; @override List<DataGridRow> get rows => _employees; @override DataGridRowAdapter buildRow(DataGridRow row) { return DataGridRowAdapter( cells: row.getCells().map<Widget>((dataGridCell) { return Container( alignment: Alignment.center, padding: const EdgeInsets.all(8.0), child: Text(dataGridCell.value.toString()), ); }).toList()); } } // 页面实现 class MultiRowEditTable extends StatefulWidget { const MultiRowEditTable({super.key}); @override State<MultiRowEditTable> createState() => _MultiRowEditTableState(); } class _MultiRowEditTableState extends State<MultiRowEditTable> { late EmployeeDataSource _dataSource; final List<Employee> _employees = [ Employee(1, 'John Doe', 'Software Engineer', 80000), Employee(2, 'Jane Smith', 'Product Manager', 95000), Employee(3, 'Bob Brown', 'Designer', 75000), ]; @override void initState() { super.initState(); _dataSource = EmployeeDataSource(_employees); } // 批量编辑弹窗 void _showBatchEditDialog() { if (_dataSource.selectedRows.isEmpty) return; String newDesignation = ''; showDialog( context: context, builder: (context) => AlertDialog( title: const Text('批量修改职位'), content: TextField( onChanged: (value) => newDesignation = value, decoration: const InputDecoration(hintText: '输入新职位'), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('取消'), ), TextButton( onPressed: () { // 更新选中行数据 for (var row in _dataSource.selectedRows) { final employee = _employees.firstWhere( (e) => e.id == row.getCells()[0].value); employee.designation = newDesignation; } _dataSource.buildDataGridRows(); _dataSource.notifyListeners(); Navigator.pop(context); }, child: const Text('确认'), ), ], ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('多行编辑表格')), body: Column( children: [ ElevatedButton( onPressed: _showBatchEditDialog, child: const Text('批量编辑选中行'), ), Expanded( child: SfDataGrid( source: _dataSource, selectionMode: SelectionMode.multiple, onSelectionChanged: (addedRows, removedRows) { setState(() { _dataSource.selectedRows = addedRows; }); }, columns: <GridColumn>[ GridColumn( columnName: 'id', label: Container( padding: const EdgeInsets.all(8.0), alignment: Alignment.center, child: const Text('ID'))), GridColumn( columnName: 'name', label: Container( padding: const EdgeInsets.all(8.0), alignment: Alignment.center, child: const Text('姓名'))), GridColumn( columnName: 'designation', label: Container( padding: const EdgeInsets.all(8.0), alignment: Alignment.center, child: const Text('职位'))), GridColumn( columnName: 'salary', label: Container( padding: const EdgeInsets.all(8.0), alignment: Alignment.center, child: const Text('薪资'))), ], ), ), ], ), ); } }
方案二:原生DataTable自定义实现
如果不想引入第三方包,可以用Flutter原生DataTable组件手动实现:
class CustomMultiRowEditTable extends StatefulWidget { const CustomMultiRowEditTable({super.key}); @override State<CustomMultiRowEditTable> createState() => _CustomMultiRowEditTableState(); } class _CustomMultiRowEditTableState extends State<CustomMultiRowEditTable> { List<Employee> _employees = [ Employee(1, 'John Doe', 'Software Engineer', 80000), Employee(2, 'Jane Smith', 'Product Manager', 95000), Employee(3, 'Bob Brown', 'Designer', 75000), ]; List<bool> _selected = []; @override void initState() { super.initState(); _selected = List.generate(_employees.length, (_) => false); } void _showBatchEdit() { final selectedEmployees = _employees .asMap() .entries .where((entry) => _selected[entry.key]) .map((entry) => entry.value) .toList(); if (selectedEmployees.isEmpty) return; String newSalary = ''; showDialog( context: context, builder: (context) => AlertDialog( title: const Text('批量修改薪资'), content: TextField( keyboardType: TextInputType.number, onChanged: (value) => newSalary = value, decoration: const InputDecoration(hintText: '输入新薪资'), ), actions: [ TextButton(onPressed: () => Navigator.pop(context), child: const Text('取消')), TextButton( onPressed: () { final salary = double.tryParse(newSalary); if (salary != null) { for (var emp in selectedEmployees) { emp.salary = salary; } setState(() {}); } Navigator.pop(context); }, child: const Text('确认'), ), ], ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('自定义多行编辑表格')), body: Column( children: [ ElevatedButton(onPressed: _showBatchEdit, child: const Text('批量编辑')), Expanded( child: SingleChildScrollView( child: DataTable( columns: const [ DataColumn(label: Text('选择')), DataColumn(label: Text('ID')), DataColumn(label: Text('姓名')), DataColumn(label: Text('职位')), DataColumn(label: Text('薪资')), ], rows: _employees.asMap().entries.map((entry) { final index = entry.key; final emp = entry.value; return DataRow( selected: _selected[index], onSelectChanged: (value) { setState(() { _selected[index] = value ?? false; }); }, cells: [ DataCell(Checkbox( value: _selected[index], onChanged: (value) { setState(() { _selected[index] = value ?? false; }); }, )), DataCell(Text(emp.id.toString())), DataCell(Text(emp.name)), DataCell(Text(emp.designation)), DataCell(Text(emp.salary.toString())), ], ); }).toList(), ), ), ), ], ), ); } }
两种方案里,第三方包的方式更省心,自带多选、状态管理等功能;原生自定义则更轻量化,适合简单场景。
内容的提问来源于stack exchange,提问作者Gautier Chuinard
相关产品推荐
相关产品推荐

