I used a PaginatedDataTable to include several iconbuttons in the Datacell. After clicking the iconbutton, I modified the value of rows[index]['status']. I want the iconbutton's icon to be displayed according to the value of rows[index]['status'].
import 'package:flutter/material.dart';
List<Map<String, dynamic>> devData() {
List<Map<String, dynamic>> data = [];
for (var i = 1; i < 15; i++) {
data.add({
'username': 'account$i',
'nickname': i % 2 == 0 ? 'Peter$i' : 'Charles$i',
'status': i % 2 == 0 ? 0 : 1,
'group': i % 2 == 0 ? 2 : 3,
});
}
return data;
}
List<Map<String, dynamic>> rows = devData();
class UserManagePage extends StatefulWidget {
const UserManagePage({super.key});
@override
State<StatefulWidget> createState() => UserManagePageState();
}
class UserManagePageState extends State<UserManagePage> {
UserManagePageState() {
rows = devData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
hoverColor: Colors.transparent,
onPressed: () {
Navigator.pop(context);
},
icon: const Icon(Icons.arrow_back_ios_new),
iconSize: 16,
color: const Color.fromRGBO(100, 100, 100, 0.5),
),
centerTitle: true,
automaticallyImplyLeading: false,
backgroundColor: WidgetStateColor.transparent,
title: const Text('用户管理',
style: TextStyle(
fontFamily: 'AlimamaFangYuanTi', fontSize: 18, fontWeight: FontWeight.w900))),
body: Container(
padding: const EdgeInsets.all(5),
alignment: const Alignment(0, 0),
child: PaginatedDataTable(
horizontalMargin: 5,
columnSpacing: 30,
header: Row(children: [
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return const UserAdd();
});
},
icon: const Icon(Icons.person_add_alt_1))
]),
columns: const [
DataColumn(label: Flexible(child: Center(child: Text('Account')))),
DataColumn(label: Flexible(child: Center(child: Text('Username')))),
DataColumn(label: Flexible(child: Center(child: Text('Group')))),
DataColumn(label: Flexible(child: Center(child: Text('Operation'))))
],
source: UserManageDate(context: context),
)),
);
}
}
class UserManageDate extends DataTableSource {
BuildContext context;
UserManageDate({required this.context});
@override
DataRow? getRow(int index) {
List<String> groups = ['Super Admin', 'Admin', 'Doctor', 'Nurse'];
return DataRow(cells: [
DataCell(Text('${rows[index]['username']}')),
DataCell(Text('${rows[index]['nickname']}')),
DataCell(Text(groups[rows[index]['group']])),
DataCell(
Flex(
direction: Axis.horizontal,
children: [
IconButton(
onPressed: () {},
icon: const Icon(
Icons.edit,
size: 20,
color: Colors.green,
),
),
//edit
IconButton(
onPressed: () {
rows[index]['status'] = rows[index]['status'] == 1 ? 0 : 1;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(rows[index]['status'] == 1 ? 'Enabled' : 'Disabled'),
action: SnackBarAction(label: 'Action', onPressed: () {}),
duration: const Duration(milliseconds: 500)));
},
icon: Icon(
rows[index]['status'] == 1 ? Icons.lock : Icons.lock_open_rounded,
size: 20,
color: rows[index]['status'] == 1 ? Colors.blue : Colors.grey,
),
),
//enable/disable
IconButton(
onPressed: () {},
icon: const Icon(
Icons.delete,
size: 20,
color: Colors.grey,
),
)
//delete:soft delete
],
), onTap: () {
print('11111222');
})
]);
}
@override
// TODO: implement isRowCountApproximate
bool get isRowCountApproximate => false;
@override
// TODO: implement rowCount
int get rowCount => rows.length;
@override
// TODO: implement selectedRowCount
int get selectedRowCount => 0;
}
This all my code.
IconButton(
onPressed: () {
rows[index]['status'] = rows[index]['status'] == 1 ? 0 : 1;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(rows[index]['status'] == 1 ? 'Enabled' : 'Disabled'),
action: SnackBarAction(label: 'Action', onPressed: () {}),
duration: const Duration(milliseconds: 500)));
},
icon: Icon(
rows[index]['status'] == 1 ? Icons.lock : Icons.lock_open_rounded,
size: 20,
color: rows[index]['status'] == 1 ? Colors.blue : Colors.grey,
),
),
1.When click this button update rows[index]['status'] value,but the screen is not update.
when data changes, you need to use setState
to update the state; otherwise, the page will not refresh. However, you are using a stateless widget, so you cannot use setState. Therefore, I recommend using Provider
for state management. Here is a demo
with your code modified accordingly.
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class UserDataProvider extends ChangeNotifier {
List<Map<String, dynamic>> _rows = [];
UserDataProvider() {
_initializeData();
}
List<Map<String, dynamic>> get rows => _rows;
void _initializeData() {
for (var i = 1; i < 15; i++) {
_rows.add({
'username': 'account$i',
'nickname': i % 2 == 0 ? 'Peter$i' : 'Charles$i',
'status': i % 2 == 0 ? 0 : 1,
'group': i % 2 == 0 ? 2 : 3,
});
}
notifyListeners();
}
void updateStatus(int index) {
_rows[index]['status'] = _rows[index]['status'] == 1 ? 0 : 1;
notifyListeners();
}
}
class UserManagePage extends StatefulWidget {
const UserManagePage({super.key});
@override
State<StatefulWidget> createState() => UserManagePageState();
}
class UserManagePageState extends State<UserManagePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
hoverColor: Colors.transparent,
onPressed: () {
Navigator.pop(context);
},
icon: const Icon(Icons.arrow_back_ios_new),
iconSize: 16,
color: const Color.fromRGBO(100, 100, 100, 0.5),
),
centerTitle: true,
automaticallyImplyLeading: false,
backgroundColor: Colors.transparent,
title: const Text('用户管理',
style: TextStyle(
fontFamily: 'AlimamaFangYuanTi',
fontSize: 18,
fontWeight: FontWeight.w900))),
body: Container(
padding: const EdgeInsets.all(5),
alignment: const Alignment(0, 0),
child: Consumer<UserDataProvider>(
builder: (context, userDataProvider, child) {
return PaginatedDataTable(
horizontalMargin: 5,
columnSpacing: 30,
header: Row(children: [
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Add User'),
content: const Text('Add User'),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Cancel')),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Add'))
]);
});
},
icon: const Icon(Icons.person_add_alt_1))
]),
columns: const [
DataColumn(
label: Flexible(child: Center(child: Text('Account')))),
DataColumn(
label: Flexible(child: Center(child: Text('Username')))),
DataColumn(
label: Flexible(child: Center(child: Text('Group')))),
DataColumn(
label: Flexible(child: Center(child: Text('Operation'))))
],
source: UserManageData(userDataProvider.rows, context),
);
},
)),
);
}
}
class UserManageData extends DataTableSource {
final List<Map<String, dynamic>> rows;
final BuildContext context;
UserManageData(this.rows, this.context);
@override
DataRow? getRow(int index) {
List<String> groups = ['Super Admin', 'Admin', 'Doctor', 'Nurse'];
return DataRow(cells: [
DataCell(Text('${rows[index]['username']}')),
DataCell(Text('${rows[index]['nickname']}')),
DataCell(Text(groups[rows[index]['group']])),
DataCell(
Flex(
direction: Axis.horizontal,
children: [
IconButton(
onPressed: () {},
icon: const Icon(
Icons.edit,
size: 20,
color: Colors.green,
),
),
//edit
IconButton(
onPressed: () {
Provider.of<UserDataProvider>(context, listen: false)
.updateStatus(index);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
rows[index]['status'] == 1 ? 'Enabled' : 'Disabled'),
action: SnackBarAction(label: 'Action', onPressed: () {}),
duration: const Duration(milliseconds: 500)));
},
icon: Icon(
rows[index]['status'] == 1
? Icons.lock
: Icons.lock_open_rounded,
size: 20,
color: rows[index]['status'] == 1 ? Colors.blue : Colors.grey,
),
),
//enable/disable
IconButton(
onPressed: () {},
icon: const Icon(
Icons.delete,
size: 20,
color: Colors.grey,
),
)
//delete:soft delete
],
), onTap: () {
print('11111222');
})
]);
}
@override
bool get isRowCountApproximate => false;
@override
int get rowCount => rows.length;
@override
int get selectedRowCount => 0;
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// return MaterialApp(
// home: BlocProvider(
// create: (_) => ColorBloc(),
// child: UserManagePage(),
// ),
// );
return MaterialApp(
home: ChangeNotifierProvider(
create: (context) => UserDataProvider(),
child: UserManagePage(),
),
);
}
}