Swipe to Remove a Widget in Flutter Using Dismissible

Are you looking to implement swipe-to-remove functionality for a widget in your Flutter application? Look no further! In this tutorial, we will go through the process of building a dismissible widget using Flutter’s Dismissible widget. By swiping a widget, you will be able to remove it from the screen with ease. Let us get started!

1. Creating a List of Widgets

First, let us set up the basic structure of our application. We will create a new Flutter project by executing flutter create project_name and replace the default lib/main.dart file with the following code:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key});

  @override
  State createState() => _MyAppState();
}

class _MyAppState extends State {
  final List stringList = ['Dismissible item 1', 'Dismissible item 2'];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dismiss Widgets Demo',
      theme: ThemeData(),
      home: Scaffold(
        body: ListView.builder(
          itemCount: stringList.length,
          itemBuilder: (BuildContext context, int index) => Container(
            height: 50,
            color: Colors.blue,
            child: Center(
              child: Text(
                stringList[index],
                style: const TextStyle(
                  fontSize: 16,
                  color: Colors.white,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

In this code, we define a MyApp widget that extends a StatefulWidget. It holds a list of strings, stringList, which represents our list of items.

Inside the build method of the corresponding _MyAppState class, we create a ListView.builder widget. This widget dynamically builds the list based on the stringList length. Each item is represented by a Container widget with a height of 50 and a blue background color. Inside the Container, we display the text from stringList using a Text widget.

2. Wrapping Our List Items With the Dismissible Widget

Now, let us make these list items dismissible. To achieve this, we will wrap the Container widget with a Dismissible widget. Therefore we modify the itemBuilder in the ListView.builder as follows:

ListView.builder(
  itemCount: stringList.length,
  itemBuilder: (BuildContext context, int index) => Dismissible(
    key: Key(stringList[index]),
    direction: DismissDirection.endToStart,
    onDismissed: (direction) {
      setState(() => stringList.removeAt(index));

      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text(
            'Item dismissed',
            textAlign: TextAlign.center,
          ),
          backgroundColor: Colors.red,
          duration: Duration(seconds: 1),
        ),
      );
    },
    child: Container(
      height: 50,
      color: Colors.blue,
      child: Center(
        child: Text(
          stringList[index],
          style: const TextStyle(
            color: Colors.white,
          ),
        ),
      ),
    ),
  ),
);

In the modified code, we wrapped the Container with a Dismissible widget. We provided a unique key for each item, which helps Flutter track the items correctly. We have set the direction property to DismissDirection.endToStart, so that swiping to the left will trigger the dismissal.

When swiping to the left the onDismissed callback will be triggered when the item is completely dismissed. Inside the callback, we remove the item from the stringList and update the UI using setState. Additionally, we display a SnackBar to provide visual feedback to the user.

We have enabled the ability to remove our widgets. However, when users start swiping, it is not clear what the swiping action will do. To improve this, we can add a background to provide better visual cues.

3. Adding a Background to Our Dismissible Widget

Let us add a background to our Dismissible widget. We do this in the background property on line 16 of the following code snippet:

Dismissible(
  key: Key(stringList[index]),
  direction: DismissDirection.endToStart,
  onDismissed: (direction) {
    setState(() => stringList.removeAt(index));
    
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text('Item dismissed', textAlign: TextAlign.center,),
        backgroundColor: Colors.red,
        duration: Duration(seconds: 1),
      ),
    );
  },
  background: Container(
    color: Colors.red,
    alignment: Alignment.centerRight,
    padding: const EdgeInsets.only(right: 16.0),
    child: const Icon(
      Icons.delete,
      color: Colors.white,
    ),
  ),
  child: Container(
    height: 50,
    color: Colors.blue,
    child: Center(
      child: Text(
        stringList[index],
        style: const TextStyle(
          color: Colors.white,
        ),
      ),
    ),
  ),
)

In this code, we have made modifications to the Dismissible widget. The Dismissible widget accepts a background property, which we have set to a red-colored Container widget. This Container widget also includes an Icon widget with a delete icon to provide visual cues for item dismissal. We also added the alignment property with the value of Alignment.centerRight to make sure that the icon is displayed on the right.

After implementing the last 2 changes the final code should look like this:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State createState() => _MyAppState();
}

class _MyAppState extends State {
  final List stringList = ['Dismissible item 1', 'Dismissible item 2'];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dismiss Widgets Demo',
      theme: ThemeData(),
      home: Scaffold(
        body: ListView.builder(
          itemCount: stringList.length,
          itemBuilder: (BuildContext context, int index) => Dismissible(
            key: Key(stringList[index]),
            direction: DismissDirection.endToStart,
            onDismissed: (direction) {
              setState(() => stringList.removeAt(index));
              
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(
                  content: Text('Item dismissed', textAlign: TextAlign.center,),
                  backgroundColor: Colors.red,
                  duration: Duration(seconds: 1),
                ),
              );
            },
            background: Container(
              color: Colors.red,
              alignment: Alignment.centerRight,
              padding: const EdgeInsets.only(right: 16.0),
              child: const Icon(
                Icons.delete,
                color: Colors.white,
              ),
            ),
            child: Container(
              height: 50,
              color: Colors.blue,
              child: Center(
                child: Text(
                  stringList[index],
                  style: const TextStyle(
                    color: Colors.white,
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Now, when you run the app and swipe an item to the left, the item will be dismissed, and you will see a red background with a delete icon. The item will be removed from the list and a SnackBar will appear at the bottom of the screen to indicate that the item has been dismissed.

4. Conclusion

In this tutorial, we explored how to implement swipe-to-remove functionality for a widget in Flutter using the Dismissible widget. By following the steps outlined in this tutorial, you can easily enable users to remove items from a list by swiping them to the side.

We started by setting up a basic Flutter project and incorporated the Dismissible widget into the ListView.builder. This allowed us to create a dynamic list of items and make each item dismissible. When an item is swiped to the left, it triggers the onDismissed callback, where we removed the item from the list, updated the UI, and provided visual feedback using a SnackBar.

To enhance the user experience, we customized the appearance of the Dismissible widget by setting a red background with a delete icon aligned to the right. You can further customize these elements to match the design of your application.

Tijn van den Eijnde
Tijn van den Eijnde
Articles: 85

Leave a Reply

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