flutter_swipe_actions 0.3.0
flutter_swipe_actions: ^0.3.0 copied to clipboard
Smooth iOS Mail-inspired swipe actions for Flutter lists, with a reusable controller and customizable action buttons.
flutter_swipe_actions #
Smooth swipe actions for Flutter lists, inspired by the iOS Mail interaction.
The package includes:
SwipeActions: wraps a list item and reveals leading or trailing actions.SwipeController: keeps only one row open at a time and exposes open/close helpers.SwipeActionButton: a reusable circular action button with a label.- RTL-aware direction handling.
- Animated item decoration and action transitions.
- Optional auto-close when an action is tapped.
Usage #
final swipeController = SwipeController();
SwipeActions(
controller: swipeController,
leadingActions: [
SwipeActionButton(
icon: const Icon(Icons.mark_email_unread_outlined),
label: 'Unread',
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
onPressed: () {},
),
],
trailingActions: [
SwipeActionButton(
icon: const Icon(Icons.flag_outlined),
label: 'Flag',
backgroundColor: Colors.orange,
foregroundColor: Colors.white,
onPressed: () {},
),
SwipeActionButton(
icon: const Icon(Icons.archive_outlined),
label: 'Archive',
backgroundColor: Colors.purple,
foregroundColor: Colors.white,
onPressed: () {},
),
],
child: const ListTile(
title: Text('Weekly update'),
subtitle: Text('Your message is ready to review.'),
),
)
Controller #
Use a shared SwipeController for every row in the same list:
final swipeController = SwipeController();
// Programmatically close the currently open item.
swipeController.closeAll();
// Read stable state without depending on an internal State object.
final hasOpenItem = swipeController.hasOpenItem;
final openSide = swipeController.openSide;
This prevents multiple rows from staying open at the same time.
Action behavior #
SwipeActionButton closes the nearest SwipeActions row after it is tapped.
This matches the usual Mail-style interaction:
SwipeActionButton(
icon: const Icon(Icons.archive_outlined),
label: 'Archive',
onPressed: archiveMessage,
)
For multi-step actions, loading states, or confirmation flows, keep the row open:
SwipeActionButton(
icon: const Icon(Icons.more_horiz),
label: 'More',
closeOnPressed: false,
onPressed: showMoreActions,
)
Custom action widgets can close the nearest row with:
SwipeActions.maybeOf(context)?.closeActions();
Callbacks #
onOpened and onClosed fire after the animation reaches its final state.
Use onOpenChanged when you need the side that opened:
SwipeActions(
onOpenChanged: (side) {
if (side == null) {
debugPrint('Closed');
} else {
debugPrint('Opened $side');
}
},
trailingActions: actions,
child: child,
)
Visual tuning #
SwipeActions accepts any Widget as an action, but SwipeActionButton is the
recommended default for normal list actions. Keep custom widgets for special
cases such as loading states, badges, or multi-step actions.
The default spacing is compact, closer to iOS Mail. You can still customize it:
SwipeActions(
actionWidth: 72,
actionSpacing: 4,
itemBorderRadius: BorderRadius.circular(20),
openedDecoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainerHighest,
),
trailingActions: const [],
child: child,
)
Compatibility #
actions is kept as an alias for trailing actions:
SwipeActions(
actions: [SwipeActionButton(...)],
child: child,
)
For new code, prefer leadingActions and trailingActions.