Flutter ListView多选删除后高亮状态未清除问题求助
Flutter ListView多选删除后高亮状态残留问题解决
问题描述
实现ListView多选删除功能时,选中多项执行删除操作后,数据已成功从Hive中移除,但原位置的Widget仍保持选中高亮状态。
问题原因
- 子组件独立维护选中状态:每个
CustomCard自行管理selected布尔值,ListView.builder复用Widget时,旧的选中状态不会自动重置。 - Hive数据加载逻辑有缺陷:
loadTransactions方法每次调用都会向静态列表追加数据,导致删除后列表数据重复。
解决方案
1. 统一由父组件管理选中状态
将选中状态的控制权移至MultiSelect组件,CustomCard不再自行维护状态,而是根据父组件的选中列表动态判断是否高亮。
修改MultiSelect代码
class MultiSelect extends StatefulWidget { const MultiSelect({super.key}); @override State<MultiSelect> createState() => _MultiSelectState(); } class _MultiSelectState extends State<MultiSelect> { late List<Transaction> selectedTransactions; @override void initState() { super.initState(); HiveAPI.loadTransactions(); selectedTransactions = []; } void toggleSelection(Transaction item) { setState(() { selectedTransactions.contains(item) ? selectedTransactions.remove(item) : selectedTransactions.add(item); }); } void delete() { setState(() { HiveAPI.deleteTransaction(selectedTransactions); selectedTransactions = []; HiveAPI.loadTransactions(); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("Multi Select Example"), actions: <Widget>[ IconButton( icon: const Icon(Icons.delete), onPressed: delete, ), ], ), body: ListView.builder( itemCount: HiveAPI.transactions.length, itemBuilder: (context, index) { final transaction = HiveAPI.transactions[index]; return CustomCard( isSelected: selectedTransactions.contains(transaction), onPress: () => toggleSelection(transaction), transaction: transaction, ); }), ); } }
修改CustomCard为无状态组件
class CustomCard extends StatelessWidget { const CustomCard({ Key? key, required this.transaction, required this.onPress, required this.isSelected, }) : super(key: key); final Transaction transaction; final VoidCallback onPress; final bool isSelected; @override Widget build(BuildContext context) { return GestureDetector( onTap: onPress, child: Container( padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0), decoration: BoxDecoration( color: isSelected ? Colors.lime.shade100 : Colors.transparent, borderRadius: const BorderRadius.all(Radius.circular(16)), ), child: Row( children: [ Container( padding: const EdgeInsets.all(8.0), decoration: BoxDecoration( color: isSelected ? Colors.lime : Colors.black, borderRadius: const BorderRadius.all(Radius.circular(200)), ), child: Icon( isSelected ? Icons.check : Icons.wallet, color: isSelected ? Colors.black : Colors.white, ), ), const SizedBox(width: 8), Text( transaction.title, style: Theme.of(context).textTheme.bodyText2, ), ], ), ), ); } }
2. 修复HiveAPI数据加载逻辑
在loadTransactions方法中先清空现有列表,避免重复添加数据:
class HiveAPI { static const String boxKey = 'transactionBox'; static const String transactionsDataKey = 'transactions'; static final box = Hive.box(boxKey); static final List<Transaction> transactions = []; static void loadTransactions() { transactions.clear(); // 清空旧数据,避免重复加载 final data = box.get(transactionsDataKey); if (data != null) { for (var transaction in data) { transactions.add( Transaction( transaction[0], transaction[1], transaction[2], transaction[3], transaction[4], ), ); } } } static void _updateTransactions() { final List transactionsPrimitive = []; for (var transaction in transactions) { transactionsPrimitive.add([ transaction.title, transaction.category, transaction.amount, transaction.type, transaction.date, ]); } box.put(transactionsDataKey, transactionsPrimitive); } static void deleteTransaction(List<Transaction> selectedTransaction) { transactions.removeWhere((item) => selectedTransaction.contains(item)); _updateTransactions(); } }
效果说明
修改后,删除操作执行时:
- 父组件清空选中列表并触发重建,ListView会根据最新数据渲染
- 每个
CustomCard动态读取父组件的选中状态,彻底解决高亮残留问题 - Hive加载数据时不再重复添加,保证列表数据准确
内容的提问来源于stack exchange,提问作者craig_ck
相关产品推荐
相关产品推荐

