I'm trying to delete multiple items in a ListView
after selecting them. Everything is working fine, the problem comes when I finish the deletion process. I can see that the items were deleted but the widgets in place are still highlighted.
Here is my code for the App:
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 select(bool value, VoidCallback callback, Transaction item) {
setState(() {
value
? selectedTransactions.remove(item)
: selectedTransactions.add(item);
callback();
});
}
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) {
return CustomCard(
onPress: (value, callback) =>
select(value, callback, HiveAPI.transactions[index]),
transaction: HiveAPI.transactions[index],
);
}),
);
}
}
This is the code to my custom widget inside the ListView
:
class CustomCard extends StatefulWidget {
const CustomCard({
Key? key,
required this.transaction,
required this.onPress,
}) : super(key: key);
final Transaction transaction;
final Function(bool, VoidCallback) onPress;
@override
State<CustomCard> createState() => _CustomCardState();
}
class _CustomCardState extends State<CustomCard> {
late bool selected;
@override
void initState() {
super.initState();
selected = false;
}
void updateUI() => setState(() => selected = !selected);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => widget.onPress(selected, updateUI),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0),
decoration: BoxDecoration(
color: selected ? 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: selected ? Colors.lime : Colors.black,
borderRadius: const BorderRadius.all(Radius.circular(200)),
),
child: Icon(
selected ? Icons.check : Icons.wallet,
color: selected ? Colors.black : Colors.white,
),
),
const SizedBox(width: 8),
Text(
widget.transaction.title,
style: Theme.of(context).textTheme.bodyText2,
),
],
),
),
);
}
}
My code for the HiveAPI
and Transaction
class:
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() {
for (var transaction in box.get(transactionsDataKey)) {
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();
}
}
class Transaction {
late String title;
late String category;
late double amount;
late int type;
late DateTime date;
Transaction(this.title, this.category, this.amount, this.type, this.date);
}
This is the list before deleting
This is the list after deleting
CodePudding user response:
You need to use Key
if you want to move or delete item in ListView.
For example:
return CustomCard(
key:Key(HiveAPI.transactions[index].title),
onPress: (value, callback) =>
select(value, callback, HiveAPI.transactions[index]),
transaction: HiveAPI.transactions[index],
);
or use other unique key if the title isn't unique