Bird
Raised Fist0
Fluttermobile~20 mins

Dismissible for swipe actions in Flutter - Mini App: Build & Ship

Choose your learning style10 modes available
Build: Swipe to Dismiss List
A screen that shows a list of items. Users can swipe left or right on an item to remove it from the list with a smooth animation.
Target UI
Swipe to Dismiss List

---------------------
| Item 1           |
|------------------|
| Item 2           |
|------------------|
| Item 3           |
|------------------|
| Item 4           |
---------------------

Swipe left or right on any item to remove it.
Display a vertical list of at least 4 items with text labels.
Each item must be wrapped in a Dismissible widget.
Swiping an item left or right removes it from the list with animation.
Show a background color and icon when swiping left or right.
Use a unique key for each Dismissible item.
Update the list state to remove the dismissed item.
Starter Code
Flutter
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: SwipeDismissScreen(),
    );
  }
}

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

  @override
  State<SwipeDismissScreen> createState() => _SwipeDismissScreenState();
}

class _SwipeDismissScreenState extends State<SwipeDismissScreen> {
  final List<String> items = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Swipe to Dismiss List'),
      ),
      body: ListView.builder(
        itemCount: items.length,
        itemBuilder: (context, index) {
          final item = items[index];
          // TODO: Wrap this ListTile with Dismissible and implement swipe to remove
          return ListTile(
            title: Text(item),
          );
        },
      ),
    );
  }
}
Task 1
Task 2
Task 3
Solution
Flutter
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: SwipeDismissScreen(),
    );
  }
}

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

  @override
  State<SwipeDismissScreen> createState() => _SwipeDismissScreenState();
}

class _SwipeDismissScreenState extends State<SwipeDismissScreen> {
  final List<String> items = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Swipe to Dismiss List'),
      ),
      body: ListView.builder(
        itemCount: items.length,
        itemBuilder: (context, index) {
          final item = items[index];
          return Dismissible(
            key: Key(item),
            background: Container(
              color: Colors.green,
              alignment: Alignment.centerLeft,
              padding: const EdgeInsets.only(left: 20),
              child: const Icon(Icons.check, color: Colors.white),
            ),
            secondaryBackground: Container(
              color: Colors.red,
              alignment: Alignment.centerRight,
              padding: const EdgeInsets.only(right: 20),
              child: const Icon(Icons.delete, color: Colors.white),
            ),
            onDismissed: (direction) {
              setState(() {
                items.removeAt(index);
              });
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('$item dismissed')),
              );
            },
            child: ListTile(
              title: Text(item),
            ),
          );
        },
      ),
    );
  }
}

We wrapped each list item in a Dismissible widget with a unique Key based on the item text. This lets Flutter track each item for swipe actions.

We added two background containers: one for swiping right (green with a check icon) and one for swiping left (red with a delete icon). These backgrounds appear as the user swipes.

In the onDismissed callback, we remove the item from the list and call setState to update the UI. We also show a small message confirming the dismissal.

This creates a smooth swipe-to-dismiss experience where users can remove items by swiping left or right.

Final Result
Completed Screen
Swipe to Dismiss List

---------------------
| Item 1           |
|------------------|
| Item 2           |
|------------------|
| Item 3           |
|------------------|
| Item 4           |
---------------------

Swipe left or right on any item to remove it with animation.
Swipe an item to the right: green background with check icon appears, item is removed.
Swipe an item to the left: red background with delete icon appears, item is removed.
A small message appears at the bottom confirming which item was dismissed.
Stretch Goal
Add an Undo button in the SnackBar to restore the last dismissed item.
💡 Hint
Store the dismissed item and its index. In the SnackBar action, insert it back into the list and call setState.

Practice

(1/5)
1. What is the main purpose of the Dismissible widget in Flutter?
easy
A. To display images in a grid layout
B. To create a button that triggers an alert
C. To allow users to swipe and remove items from a list
D. To animate text color changes

Solution

  1. Step 1: Understand the widget's function

    The Dismissible widget is designed to let users swipe list items to remove them.
  2. Step 2: Compare options with the widget's purpose

    Only To allow users to swipe and remove items from a list describes swiping to remove items, which matches Dismissible's role.
  3. Final Answer:

    To allow users to swipe and remove items from a list -> Option C
  4. Quick Check:

    Dismissible = swipe to remove [OK]
Hint: Dismissible = swipe to delete list items [OK]
Common Mistakes:
  • Confusing Dismissible with buttons or animations
  • Thinking it manages image layouts
  • Assuming it changes text colors
2. Which of the following is the correct way to assign a unique key to a Dismissible widget?
easy
A. key: Key('item_1')
B. key: UniqueKey()
C. key: ValueKey(1)
D. All of the above

Solution

  1. Step 1: Review key types for Dismissible

    Flutter requires a unique key for each Dismissible. Key, UniqueKey(), and ValueKey() are all valid ways to create unique keys.
  2. Step 2: Confirm all options are valid

    Each option shows a valid key assignment method, so all are correct.
  3. Final Answer:

    All of the above -> Option D
  4. Quick Check:

    Any unique key type works [OK]
Hint: Any unique Key subclass works for Dismissible keys [OK]
Common Mistakes:
  • Using non-unique keys like constant strings for all items
  • Omitting the key parameter
  • Using keys that are not unique per item
3. Given this code snippet, what happens when the user swipes the list item?
Dismissible(
  key: Key('item1'),
  onDismissed: (direction) {
    items.removeAt(0);
  },
  child: ListTile(title: Text('Item 1')),
)
medium
A. The first item is removed from the list
B. Nothing happens because the key is wrong
C. The app crashes due to missing setState
D. The item is duplicated instead of removed

Solution

  1. Step 1: Understand onDismissed callback

    The onDismissed callback removes the first item from the items list when swiped.
  2. Step 2: Analyze the effect of removing item at index 0

    Removing at index 0 deletes the first item, so the list updates accordingly.
  3. Final Answer:

    The first item is removed from the list -> Option A
  4. Quick Check:

    onDismissed removes item at index 0 [OK]
Hint: onDismissed callback removes the swiped item [OK]
Common Mistakes:
  • Assuming key error prevents removal
  • Forgetting to update the list state
  • Thinking swipe duplicates items
4. What is wrong with this Dismissible usage?
Dismissible(
  key: Key('item'),
  onDismissed: (direction) {
    items.removeAt(index);
  },
  child: ListTile(title: Text('Item')),
)
medium
A. The key is not unique for each item
B. The onDismissed callback is missing
C. The child widget is not a ListTile
D. The index variable is not defined

Solution

  1. Step 1: Check the key uniqueness

    The key is Key('item') which is constant and not unique per item, causing issues in lists.
  2. Step 2: Verify other parts

    The onDismissed callback exists, child is a ListTile, and index is assumed defined, so no issues there.
  3. Final Answer:

    The key is not unique for each item -> Option A
  4. Quick Check:

    Keys must be unique per Dismissible [OK]
Hint: Keys must be unique strings or objects per item [OK]
Common Mistakes:
  • Using same key for all items
  • Ignoring key importance in lists
  • Assuming onDismissed is optional
5. You want to show a red background with a trash icon when swiping a Dismissible item to the left. Which code snippet correctly implements this?
hard
A. background: Container(color: Colors.red)
B. background: Container(color: Colors.red, child: Icon(Icons.delete, color: Colors.white))
C. background: Container(color: Colors.white, child: Icon(Icons.delete, color: Colors.red))
D. background: Icon(Icons.delete, color: Colors.red)

Solution

  1. Step 1: Understand background property

    The background expects a widget behind the item during swipe, usually a colored container with an icon.
  2. Step 2: Check each option's correctness

    The snippet with Container(color: Colors.red, child: Icon(Icons.delete, color: Colors.white)) provides a red background with a visible white trash icon. Others lack a container, the icon, or use colors that do not produce a red background with a visible trash icon.
  3. Final Answer:

    background: Container(color: Colors.red, child: Icon(Icons.delete, color: Colors.white)) -> Option B
  4. Quick Check:

    Red container + white icon = correct swipe background [OK]
Hint: Use Container with color and Icon for swipe background [OK]
Common Mistakes:
  • Using icon alone without container
  • Wrong colors making icon invisible
  • Missing icon in background
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard