Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 19 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!-- [![Build][github_action_badge]][github_action] -->

[![Pub][pub_badge]][pub] [![BuyMeACoffee][buy_me_a_coffee_badge]][buy_me_a_coffee]

[<img src="https://raw.githubusercontent.com/letsar/flutter_slidable/assets/flutter_favorite.png" width="100" />][flutter_favorite] **Slidable is a [Flutter Favorite][flutter_favorite] package!**


# flutter_slidable

A Flutter implementation of slidable list item with directional slide actions that can be dismissed.
Expand All @@ -12,12 +12,12 @@ A Flutter implementation of slidable list item with directional slide actions th

Our top sponsors are shown below! [[Become a Sponsor](https://github.com/sponsors/letsar)]

<table>
<table>
<tbody>
<tr>
<td align="center">
<a href="https://getstream.io/chat/flutter/tutorial/?utm_source=PubDev&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=PubDev_Jan2022_FlutterChat&utm_term=slidable" target="_blank"><img width="250px" src="https://stream-blog.s3.amazonaws.com/blog/wp-content/uploads/fc148f0fc75d02841d017bb36e14e388/Stream-logo-with-background-.png"/></a><br/><span><a href="https://getstream.io/chat/flutter/tutorial/?utm_source=PubDev&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=PubDev_Jan2022_FlutterChat&utm_term=slidable" target="_blank">Try the Flutter Chat Tutorial &nbsp💬</a></span>
</td>
</td>
</tr>
</tbody>
</table>
Expand All @@ -28,16 +28,16 @@ You can read this small guide to migrate from the 0.6 to the 1.0 version: https:

## Features

* Accepts start (left/top) and end (right/bottom) action panes.
* Can be dismissed.
* 4 built-in action panes.
* 2 built-in slide action widgets.
* 1 built-in dismiss animation.
* You can easily create custom layouts and animations.
* You can use a builder to create your slide actions if you want special effects during animation.
* Closes when a slide action has been tapped (overridable).
* Closes when the nearest `Scrollable` starts to scroll (overridable).
* Option to disable the slide effect easily.
- Accepts start (left/top) and end (right/bottom) action panes.
- Can be dismissed.
- 4 built-in action panes.
- 2 built-in slide action widgets.
- 1 built-in dismiss animation.
- You can easily create custom layouts and animations.
- You can use a builder to create your slide actions if you want special effects during animation.
- Closes when a slide action has been tapped (overridable).
- Closes when the nearest `Scrollable` starts to scroll (overridable).
- Option to disable the slide effect easily.

## Install

Expand Down Expand Up @@ -78,14 +78,14 @@ Slidable(
onPressed: doNothing,
backgroundColor: Color(0xFFFE4A49),
foregroundColor: Colors.white,
icon: Icons.delete,
icon: const Icon(Icons.delete),
label: 'Delete',
),
SlidableAction(
onPressed: doNothing,
backgroundColor: Color(0xFF21B7CA),
foregroundColor: Colors.white,
icon: Icons.share,
icon: const Icon(Icons.share),
label: 'Share',
),
],
Expand All @@ -101,14 +101,14 @@ Slidable(
onPressed: doNothing,
backgroundColor: Color(0xFF7BC043),
foregroundColor: Colors.white,
icon: Icons.archive,
icon: const Icon(Icons.archive),
label: 'Archive',
),
SlidableAction(
onPressed: doNothing,
backgroundColor: Color(0xFF0392CF),
foregroundColor: Colors.white,
icon: Icons.save,
icon: const Icon(Icons.save),
label: 'Save',
),
],
Expand Down Expand Up @@ -188,10 +188,11 @@ I'm working on my packages on my free-time, but I don't have as much time as I w

Feel free to contribute to this project.

If you find a bug or want a feature, but don't know how to fix/implement it, please fill an [issue][issue].
If you find a bug or want a feature, but don't know how to fix/implement it, please fill an [issue][issue].
If you fixed a bug or implemented a feature, please send a [pull request][pr].

<!-- Links -->

[github_action_badge]: https://github.com/letsar/flutter_slidable/workflows/Build/badge.svg
[github_action]: https://github.com/letsar/flutter_slidable/actions
[pub_badge]: https://img.shields.io/pub/v/flutter_slidable.svg
Expand Down
16 changes: 8 additions & 8 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
onPressed: doNothing,
backgroundColor: Color(0xFFFE4A49),
foregroundColor: Colors.white,
icon: Icons.delete,
icon: Icon(Icons.delete),
label: 'Delete',
),
SlidableAction(
onPressed: doNothing,
backgroundColor: Color(0xFF21B7CA),
foregroundColor: Colors.white,
icon: Icons.share,
icon: Icon(Icons.share),
label: 'Share',
),
],
Expand All @@ -64,14 +64,14 @@ class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
onPressed: (_) => controller.openEndActionPane(),
backgroundColor: const Color(0xFF7BC043),
foregroundColor: Colors.white,
icon: Icons.archive,
icon: Icon(Icons.archive),
label: 'Archive',
),
SlidableAction(
onPressed: (_) => controller.close(),
backgroundColor: const Color(0xFF0392CF),
foregroundColor: Colors.white,
icon: Icons.save,
icon: Icon(Icons.save),
label: 'Save',
),
],
Expand All @@ -98,14 +98,14 @@ class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
onPressed: doNothing,
backgroundColor: Color(0xFFFE4A49),
foregroundColor: Colors.white,
icon: Icons.delete,
icon: Icon(Icons.delete),
label: 'Delete',
),
SlidableAction(
onPressed: doNothing,
backgroundColor: Color(0xFF21B7CA),
foregroundColor: Colors.white,
icon: Icons.share,
icon: Icon(Icons.share),
label: 'Share',
),
],
Expand All @@ -122,14 +122,14 @@ class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
onPressed: doNothing,
backgroundColor: Color(0xFF7BC043),
foregroundColor: Colors.white,
icon: Icons.archive,
icon: Icon(Icons.archive),
label: 'Archive',
),
SlidableAction(
onPressed: doNothing,
backgroundColor: Color(0xFF0392CF),
foregroundColor: Colors.white,
icon: Icons.save,
icon: Icon(Icons.save),
label: 'Save',
),
],
Expand Down
4 changes: 2 additions & 2 deletions example/lib/main_demo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ class SlideAction extends StatelessWidget {
onPressed: (_) {
print(icon);
},
icon: icon,
icon: Icon(icon),
label: 'hello',
);
}
Expand All @@ -291,7 +291,7 @@ class Tile extends StatelessWidget {
return ActionTypeListener(
child: GestureDetector(
onTap: () {
print('$text');
print(text);
},
onLongPress: () => Slidable.of(context)!.openEndActionPane(),
child: Container(
Expand Down
2 changes: 1 addition & 1 deletion example/lib/main_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ class SlideAction extends StatelessWidget {
backgroundColor: color,
foregroundColor: Colors.white,
onPressed: (_) {},
icon: icon,
icon: Icon(icon),
label: label,
);
}
Expand Down
2 changes: 1 addition & 1 deletion example/lib/main_outside_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ class SlideAction extends StatelessWidget {
backgroundColor: color,
foregroundColor: Colors.white,
onPressed: (_) {},
icon: icon,
icon: Icon(icon),
label: 'hello',
);
}
Expand Down
16 changes: 9 additions & 7 deletions lib/src/actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,8 @@ class CustomSlidableAction extends StatelessWidget {

@override
Widget build(BuildContext context) {
final effectiveForegroundColor = foregroundColor ??
(ThemeData.estimateBrightnessForColor(backgroundColor) ==
Brightness.light
? Colors.black
: Colors.white);
final effectiveForegroundColor =
foregroundColor ?? (ThemeData.estimateBrightnessForColor(backgroundColor) == Brightness.light ? Colors.black : Colors.white);

return Expanded(
flex: flex,
Expand Down Expand Up @@ -142,6 +139,7 @@ class SlidableAction extends StatelessWidget {
this.label,
this.borderRadius = BorderRadius.zero,
this.padding,
this.labelStyle,
}) : assert(flex > 0),
assert(icon != null || label != null),
super(key: key);
Expand All @@ -162,7 +160,7 @@ class SlidableAction extends StatelessWidget {
final SlidableActionCallback? onPressed;

/// An icon to display above the [label].
final IconData? icon;
final Widget? icon;

/// The space between [icon] and [label] if both set.
///
Expand All @@ -178,13 +176,16 @@ class SlidableAction extends StatelessWidget {
/// Padding of the OutlinedButton
final EdgeInsets? padding;

/// The style to use for the [label].
final TextStyle? labelStyle;

@override
Widget build(BuildContext context) {
final children = <Widget>[];

if (icon != null) {
children.add(
Icon(icon),
icon!,
);
}

Expand All @@ -199,6 +200,7 @@ class SlidableAction extends StatelessWidget {
Text(
label!,
overflow: TextOverflow.ellipsis,
style: labelStyle,
),
);
}
Expand Down
4 changes: 2 additions & 2 deletions test/actions_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void main() {
children: [
SlidableAction(
onPressed: (_) => logs.add('pressed'),
icon: Icons.ac_unit,
icon: const Icon(Icons.ac_unit),
)
],
),
Expand All @@ -99,7 +99,7 @@ void main() {
children: [
SlidableAction(
onPressed: (_) => logs.add('pressed'),
icon: Icons.ac_unit,
icon: const Icon(Icons.ac_unit),
label: 'my_label',
)
],
Expand Down
37 changes: 16 additions & 21 deletions test/dismissible_pane_test.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_slidable/src/action_pane_motions.dart';
import 'package:flutter_slidable/src/actions.dart';
Expand Down Expand Up @@ -34,8 +33,8 @@ void main() {
),
motion: const BehindMotion(),
children: [
SlidableAction(onPressed: (_) {}, icon: Icons.share),
SlidableAction(onPressed: (_) {}, icon: Icons.delete),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.share)),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.delete)),
],
),
child: const SizedBox.expand(),
Expand Down Expand Up @@ -77,8 +76,8 @@ void main() {
),
motion: const BehindMotion(),
children: [
SlidableAction(onPressed: (_) {}, icon: Icons.share),
SlidableAction(onPressed: (_) {}, icon: Icons.delete),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.share)),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.delete)),
],
),
child: const SizedBox.expand(),
Expand Down Expand Up @@ -124,8 +123,8 @@ void main() {
),
motion: const BehindMotion(),
children: [
SlidableAction(onPressed: (_) {}, icon: Icons.share),
SlidableAction(onPressed: (_) {}, icon: Icons.delete),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.share)),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.delete)),
],
),
child: const SizedBox.expand(),
Expand All @@ -149,9 +148,7 @@ void main() {
expect(dismissed, isTrue);
});

testWidgets(
'startActionPane cannot be drag dismissed if dragDismissible is false',
(tester) async {
testWidgets('startActionPane cannot be drag dismissed if dragDismissible is false', (tester) async {
bool dismissed = false;
void handleDismissed() {
dismissed = true;
Expand All @@ -174,8 +171,8 @@ void main() {
),
motion: const BehindMotion(),
children: [
SlidableAction(onPressed: (_) {}, icon: Icons.share),
SlidableAction(onPressed: (_) {}, icon: Icons.delete),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.share)),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.delete)),
],
),
child: const SizedBox.expand(),
Expand All @@ -199,9 +196,7 @@ void main() {
expect(dismissed, isFalse);
});

testWidgets(
'when the drag is not past the dismissThreshold, the Slidable stays open',
(tester) async {
testWidgets('when the drag is not past the dismissThreshold, the Slidable stays open', (tester) async {
bool dismissed = false;
void handleDismissed() {
dismissed = true;
Expand All @@ -226,8 +221,8 @@ void main() {
),
motion: const BehindMotion(),
children: [
SlidableAction(onPressed: (_) {}, icon: Icons.share),
SlidableAction(onPressed: (_) {}, icon: Icons.delete),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.share)),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.delete)),
],
),
child: const SizedBox.expand(),
Expand Down Expand Up @@ -282,8 +277,8 @@ void main() {
),
motion: const BehindMotion(),
children: [
SlidableAction(onPressed: (_) {}, icon: Icons.share),
SlidableAction(onPressed: (_) {}, icon: Icons.delete),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.share)),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.delete)),
],
),
child: const SizedBox.expand(),
Expand Down Expand Up @@ -340,8 +335,8 @@ void main() {
),
motion: const BehindMotion(),
children: [
SlidableAction(onPressed: (_) {}, icon: Icons.share),
SlidableAction(onPressed: (_) {}, icon: Icons.delete),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.share)),
SlidableAction(onPressed: (_) {}, icon: const Icon(Icons.delete)),
],
),
child: Builder(
Expand Down
Loading