Flutter ListView: Only one item name on the list is called when onDismissed

Issue

I am using a ListView.Builder to display my data to the screen which is working very fine, then I implemented the Dismiss and onDismiss function which seem to be working fine but it I try to dismiss item-A it will dismiss it from the screen but on the showSnackBar its displaying that Item-Z was deleted, if I deleted item-B it still gives me the name of of item-Z on the showSnackBar, I added more items to the data List which made item-Z now item-X but if I swipe its still shows me that the new item-Z has been deleted, then I tried deleting the Last Item which is the item-Z and it gave me an error

[. Exception caught by animation library
═════════════════════════════════ The following RangeError was thrown
while notifying listeners for AnimationController:
RangeError (index): Invalid value: Not in inclusive range 0..3: 4

When the exception was thrown, this was the stack
#0 List.[] (dart:core-patch/growable_array.dart:177:60)
#1 _ListsState.build.. package:another_test/list_widget.dart:81. ]

this is the code down bellow

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import './list_model.dart';

class Lists extends StatefulWidget {
  @override
  _ListsState createState() => _ListsState();
}

class _ListsState extends State<Lists> {
  List<ItemLists> items = [
    ItemLists(
      title: 'Best Music of the Year',
      discription: 'Davido',
      favorite: false,
    ),
    ItemLists(
      title: 'Best Album Cover design',
      discription: 'Brighter Press',
      favorite: false,
    ),
    ItemLists(
      title: 'Best Vocalist',
      discription: 'Simi-Sola',
      favorite: false,
    ),
    ItemLists(
      title: 'Best Danced',
      discription: 'Black Camaru',
      favorite: false,
    ),
    ItemLists(
      title: 'Best Performance',
      discription: 'Shofeni-Were',
      favorite: false,
    ),
    ItemLists(
      title: 'Best Act',
      discription: 'You Want to See Craze',
      favorite: false,
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Container(
      child: ListView.builder(
        scrollDirection: Axis.vertical,
        shrinkWrap: true,
        itemBuilder: (context, index) {
          return Dismissible(
            key: ObjectKey(items[index]),
            background: Container(
              color: Colors.red,
            ),
            child: Card(
                child: ListTile(
              leading: new IconButton(
                  icon: Icon(
                    Icons.star,
                    color: items[index].favorite ? Colors.green : Colors.grey,
                  ),
                  tooltip: 'Add to Favorite',
                  onPressed: () {
                    setState(() {
                      items[index].favorite = !items[index].favorite;
                    });
                  }),
              title: Text('${items[index].title}'),
              subtitle: Text('${items[index].discription}'),
              trailing:
                  IconButton(icon: Icon(Icons.calendar_today), onPressed: null),
            )),
            onDismissed: (direction) {
              // Remove the item from the data source.
              setState(() {
                items.removeAt(index);
              });
              Scaffold.of(context).showSnackBar(
                SnackBar(
                  content: Text('${items[index]?.title} Deleted'),
                ),
              );
            },
          );
        },
        itemCount: items.length,
      ),
    );
  }
}

and the data model code down bellow

class ItemLists {
  String title;
  String discription;
  bool favorite;

  ItemLists({this.title, this.discription, this.favorite});
}

from the screenshoot bellow you will see i deleted a different item but it was still showing me that i deleted the last item which is still on the page

enter image description here

Solution

Snackbar is trying to get the name, but the item is already deleted by that time. The solution would be to get the title name before the item is deleted from the list.

Change onDismissed to this:

onDismissed: (direction) {
  // Remove the item from the data source.
  // get the title of the item before it is deleted
  final String myTitle = items[index].title;
  setState(() {
    items.removeAt(index);
  });
  Scaffold.of(context).showSnackBar(
    SnackBar(
      content: Text('$myTitle Deleted'),
    ),
  );
};

Answered By – ambiguous58

Answer Checked By – Pedro (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *