A high-performant slidable Panel that can show actions in different positions, and also can expand the action item when the panel is opening
Features
this package uses some syntax sugar of Dart 3.0, please create issues if you want to use this package in Dart 2.x, I will remove those syntax sugars and migrate it to Dart 2.x
- When the panel is closed/dismissed, no actions would be painted and laid out.
- The animation of actions (e.g., expanding/collapsing a specific action) will be scoped and not result in the re-layout and re-painting of the entire
SlidablePanel - control the
SlidablePaneland actions programmatically usingSlideController, not limited to gestures.
All action widgets can be expanded when the SlidablePanel is opening.
Different Motions
ActionMotion.drawer
ActionMotion.scroll
ActionMotion.behind
Disable gesture sliding
By setting gestureDisabled: true, you could avoid gesture sliding and continue sliding via SlideController programmatically
SlidablePanel(
...
gestureDisabled: true,
...
)
Initial Opened Position
By specifying the initOpenedPosition of SlideController, you could open actions at the initOpenedPosition without using WidgetsBinding.instance.addPostFrameCallback.
you should ensure there are actions at the specified
initOpenedPosition
final SlideController _slideController = SlideController(
usePreActionController: true,
usePostActionController: true,
initOpenedPosition: ActionPosition.pre,
);
Getting started
import 'package:flutter/material.dart';
import 'package:flutter_slidable_panel/flutter_slidable_panel.dart';
class SizedSlidableExample extends StatefulWidget {
const SizedSlidableExample({super.key});
@override
State<SizedSlidableExample> createState() => _SizedSlidableExampleState();
}
class _SizedSlidableExampleState extends State<SizedSlidableExample> {
final SlideController _slideController = SlideController(
usePreActionController: true,
usePostActionController: true,
);
@override
void dispose() {
_slideController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sized Slidable Example'),
),
body: Center(
child: SlidablePanel(
controller: _slideController,
maxSlideThreshold: 0.8,
axis: Axis.horizontal,
preActions: [
TextButton(
onPressed: () {
_slideController.toggleAction(0);
},
style: TextButton.styleFrom(
backgroundColor: Colors.greenAccent,
shape: const RoundedRectangleBorder(),
),
child: const Text("PreAction"),
),
TextButton(
onPressed: () {
_slideController.toggleAction(1);
},
style: TextButton.styleFrom(
backgroundColor: Colors.redAccent,
shape: const RoundedRectangleBorder(),
),
child: const Text("PreAction"),
),
],
postActions: [
TextButton(
onPressed: () {
_slideController.toggleAction(0);
},
style: TextButton.styleFrom(
backgroundColor: Colors.greenAccent,
shape: const RoundedRectangleBorder(),
),
child: const Text("PostAction"),
),
TextButton(
onPressed: () {
_slideController.toggleAction(1);
},
style: TextButton.styleFrom(
backgroundColor: Colors.redAccent,
shape: const RoundedRectangleBorder(),
),
child: const Text("PostAction"),
),
],
child: GestureDetector(
onTap: () {
_slideController.dismiss();
},
child: const DecoratedBox(
decoration: BoxDecoration(color: Colors.blue),
child: SizedBox(
width: 250,
height: 100,
child: Center(
child: Text(
'Slide me',
),
),
),
),
),
),
),
);
}
}
Usage
create a SlideController
usePreActionControllerindicates if you want to enable expanding/collapsing the pre actionsusePostActionControllerindicates if you want to enable expanding/collapsing the post actions.
if
usePreActionControllerorusePostActionControlleris set to true, the corresponding ActionController would be created and bound to RenderSlideAction automatically
- invoking SlideController.expand/SlideController.collapse/SlideController.toggleAction only takes effects for two cases:
usePreActionControlleris true and the currentopenedPositionis ActionPosition.preusePostActionControlleris true and the currentopenedPositionis ActionPosition.post
final SlideController _slideController = SlideController(
usePreActionController: true,
usePostActionController: true,
);
use different motion and alignment at different positions
SlidablePanel.preActionLayout and SlidablePanel.postActionLayout accept ActionLayout as parameters.
-
You could determine how to layout the actions at the different positions by specifying:
when using
ActionAlignment.flex, you could give an action a specific flex value usingActionItem. Other actions not wrapped inActionItemwould have a default flex value of 1.ActionAlignment.spaceEvenlywould ignoreActionItem
ActionLayout(
alignment: ActionAlignment.spaceEvenly || ActionAlignment.flex,
)
- You could also determine which motion to use:
ActionLayout(
motion: ActionMotion.behind || ActionMotion.drawer || ActionMotion.scroll
)
Do something when starting sliding
You could set onSlideStart to do some work when starting sliding,
e.g., you want to dismiss all other SlidablePanel when starting sliding.
SlidablePanel(
/// other code
onSlideStart: <your function>,
/// other code
)
Use SlideController programmatically
open the panel
SlideController.open({
ActionPosition position = ActionPosition.pre,
Curve curve = Curves.easeInOut,
Duration duration = const Duration(milliseconds: 300),
VoidCallback? onOpened,
});
dismiss the panel
SlideController.dismiss({
Curve curve = Curves.easeInOut,
Duration duration = const Duration(milliseconds: 300),
VoidCallback? onDismissed,
})
check the current opened position
SlideController.openedPosition
- opened
ActionPosition.prefor horizontal and vertical
- opened
ActionPosition.postfor horizontal and vertical
expand the index action at the opened position
index is the index in SlidablePanel.preActions or SlidablePanel.postActions
it will try to expand the
indexaction at the current opened position if this panel is opened;
if this panel is closed/dismissed, it has no effects
if the current opened position has no associated
ActionController, it also has no effects
you could associate
ActionControllerto a specific position by settingusePreActionControllerorusePostActionControllerastrue.
SlideController.expand(
int index, {
Curve curve = Curves.easeInOut,
Duration duration = const Duration(milliseconds: 150),
})
collapse the index action at the opened position
SlideController.collapse(
int index, {
required ActionPosition position,
Curve curve = Curves.easeInOut,
Duration duration = const Duration(milliseconds: 150),
})
toggle the index action at the opened position
SlideController.toggleAction(
int index, {
Curve curve = Curves.easeInOut,
Duration duration = const Duration(milliseconds: 150),
})
detect if the index action is expanded
bool SlideController.hasExpandedAt(int index)