user6274128
user6274128

Reputation:

Flutter ListView delete and undo operation

How can I implement a ListView that has a Dismissible widget, and when I swipe, I can delete the item, but how can I bring it back when tapping say a SnackBar's action. Can anyone give me example for this? Here is what I am at in my State class.

List<String> _list = List.generate(10, (index) => "${index}");

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text("App")),
    body: ListView.builder(
      itemCount: _list.length,
      itemBuilder: (context, index) {
        return Dismissible(
          key: Key(_list[index]),
          background: Container(color: Colors.red,),
          child: ListTile(title: Text(_list[index])),
          onDismissed: (direction) => setState(() => _list.removeAt(index))
        );
      },
    )
  );
} 

Upvotes: 10

Views: 8249

Answers (3)

Achmad Irfanda
Achmad Irfanda

Reputation: 11

in version 2.0.3 you can this code :

() {
        setState(() {
          var delete = widget.ingerdientItems.removeAt(index);
          
          ScaffoldMessenger.of(context).showSnackBar(SnackBar(
              content: Text(
            '${item.ingredientName} Berhasil Dihapus!',
            style: Theme.of(context)
                .textTheme
                .bodyText1
                .copyWith(color: Theme.of(context).backgroundColor)),
            action: SnackBarAction(
                label: "UNDO",
                onPressed: () => setState(() => widget.ingerdientItems.insert(index, delete),) // this is what you needed
              ),)
          );
        });
      },

Upvotes: 1

Kennedy Owusu
Kennedy Owusu

Reputation: 6070

If you are retrieving data from a remote server such as firestore, follow this example below:

StreamBuilder<QuerySnapshot>(
            stream: db.collection("collection name").snapshots(),
            // ignore: missing_return
            builder:
                (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
              if (snapshot.hasError) {
                return Center(child: Text('Sorry something went wrong'));
              }

              if (snapshot.connectionState == ConnectionState.waiting) {
                return Center(child: CircularProgressIndicator());
              }
              return ListView.builder(
                  itemCount: snapshot.data.docs.length,
                  shrinkWrap: true,
                  physics: NeverScrollableScrollPhysics(),
                  itemBuilder: (context, index){
                    DocumentSnapshot document = snapshot.data.docs[index];
                    final documentID = snapshot.data.docs[index].id;
                    final list = snapshot.data.docs;
                    return Dismissible(
                      confirmDismiss: (direction) => promptUser(direction), //U can use showDialog to build this method for confirmation if need be.

                      // Each Dismissible must contain a Key. Keys allow
                      // Flutter to uniquely identify widgets.
                      key: Key(documentID),
                      onDismissed: (direction){
                        removeFromDb(documentID);
                        setState(() {
                          // Remove the item from the data source.
                          list.removeAt(index);

                          String action;
                          if (direction == DismissDirection.endToStart) {
                            removeFromDb(documentID);
                            action = "deleted";
                          }

                          _key.currentState
                            ..removeCurrentSnackBar()
                            ..showSnackBar(
                              SnackBar(
                                content: Text("Data $documentID $action"),
                                action: SnackBarAction(
                                    label: "UNDO",
                                    onPressed: () => setState(() => list.insert(index, deletedItem),)
                                ),
                              ),
                            );
                        });
                      },
                      // Show a red background as the item is swiped away
                      background: Container(
                        color: Colors.amber,
                        padding: EdgeInsets.symmetric(horizontal: 20),
                        alignment: AlignmentDirectional.centerEnd,
                        child: Icon(
                          Icons.delete,
                          color: Colors.white,
                        ),
                      ),
                      child: GestureDetector(
                        onTap: () => _onSelected(index),
                        child: Container(
                          //==> change bg color when index is selected ==>
                          color: _selectedIndex != null && _selectedIndex == index
                              ? Colors.grey[100]
                              : Colors.white,
                          padding: EdgeInsets.only(top: 15, left: 10, right: 10),
                                height: 180,
                                width: double.maxFinite,
                          child: Card(
                            elevation: 5,
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(5),
                            ),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.start,
                              crossAxisAlignment: CrossAxisAlignment.center,
                              children: [
                                Padding(
                                  padding: EdgeInsets.all(5.0),),
                                Padding(
                                  padding: EdgeInsets.only(top: 30, left: 1),
                                  child: Column(
                                    children: [
                                      Text(
                                        document.data()['same name in document/field'],
                                        style: TextStyle(
                                          decorationStyle: TextDecorationStyle.double,
                                          color: Colors.black,
                                          fontSize: 20,
                                          fontWeight: FontWeight.w700,
                                        ),
                                      ),
                                      SizedBox(
                                        height: 9,
                                      ),
                                      Text(document.data()['same name in document/field'],
                                        style: TextStyle(
                                          decorationStyle: TextDecorationStyle.double,
                                          color: Colors.black87,
                                          fontSize: 16,
                                        ),),
                                      SizedBox(
                                        height: 9,
                                      ),
                                      Text(document.data()['same name in document/field'],
                                        style: TextStyle(
                                          decorationStyle: TextDecorationStyle.double,
                                          color: Colors.black87,
                                        ),
                                      ),
                                      SizedBox(
                                        height: 6,
                                      ),
                                      Text(document.data()['same name in document/field'],
                                        style: TextStyle(
                                          decorationStyle: TextDecorationStyle.double,
                                          color: Colors.black87,
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                                SizedBox(
                                  width: 15,
                                ),
                                Container(
                                  width: 1,
                                  height: 130,
                                  color: Colors.black54,
                                ),
                                SizedBox(
                                  width: 8,
                                ),
                                Padding(
                                  padding: EdgeInsets.only(top: 20, bottom: 20),
                                  child: Container(
                                      height: 120,
                                      width: 145,
                                      child: SingleChildScrollView(
                                          child: Align(
                                            alignment: Alignment.center,
                                            child: Text(
                                              document.data()['same name in document/field'],
                                              style: TextStyle(
                                                  color: Colors.black
                                              ),
                                            ),
                                          ))),
                                ),
                              ],
                            ),
                          ),
                        ),
                      ),
                    );
                  }
              );
              
            })

Couldn't show screenshot but this will work alright especially if you understand Firestore

Upvotes: 1

CopsOnRoad
CopsOnRoad

Reputation: 267554

All you needed is

_list.insert(index, yourDeletedItem);

Here is the complete code with SnackBar added.

GlobalKey<ScaffoldState> _key = GlobalKey(); // added
List<String> _list = List.generate(10, (index) => "${index}");

@override
Widget build(BuildContext context) {
  return Scaffold(
    key: _key, // added
    appBar: AppBar(title: Text("App")),
    body: ListView.builder(
      itemCount: _list.length,
      itemBuilder: (context, index) {
        return Dismissible(
          key: Key(_list[index]),
          child: ListTile(title: Text(_list[index])),
          background: Container(color: Colors.red),
          onDismissed: (direction) {
            setState(() {
              // added this block 
              String deletedItem = _list.removeAt(index);
              _key.currentState
               ..removeCurrentSnackBar()
               ..showSnackBar(
                SnackBar(
                  content: Text("Deleted \"${deletedItem}\""),
                  action: SnackBarAction(
                    label: "UNDO",
                    onPressed: () => setState(() => _list.insert(index, deletedItem),) // this is what you needed
                  ),
                ),
              );
            });
          },
        );
      },
    ),
  );
}

Screenshot

enter image description here

Upvotes: 21

Related Questions