@@ -104,7 +104,7 @@ class SlidableDelegateContext {
104104 const SlidableDelegateContext (
105105 this .slidable,
106106 this .showActions,
107- this .dragExtent ,
107+ this .dragSign ,
108108 this .controller,
109109 );
110110
@@ -122,7 +122,7 @@ class SlidableDelegateContext {
122122 /// Whether the actions have to be shown.
123123 final bool showActions;
124124
125- final double dragExtent ;
125+ final double dragSign ;
126126
127127 /// The animation controller which value depends on `dragExtent` .
128128 final AnimationController controller;
@@ -193,10 +193,10 @@ abstract class SlidableStackDelegate extends SlidableDelegate {
193193 Widget buildActions (BuildContext context, SlidableDelegateContext ctx) {
194194 final animation = new Tween (
195195 begin: Offset .zero,
196- end: ctx.createOffset (ctx.totalActionsExtent * ctx.dragExtent.sign ),
196+ end: ctx.createOffset (ctx.totalActionsExtent * ctx.dragSign ),
197197 ).animate (ctx.controller);
198198
199- if (ctx.controller.value != .0 && ctx.dragExtent != . 0 ) {
199+ if (ctx.controller.value != .0 ) {
200200 return new Container (
201201 child: new Stack (
202202 children: < Widget > [
@@ -231,7 +231,7 @@ class SlidableStrechDelegate extends SlidableStackDelegate {
231231 Widget buildStackActions (BuildContext context, SlidableDelegateContext ctx) {
232232 final animation = new Tween (
233233 begin: Offset .zero,
234- end: ctx.createOffset (ctx.totalActionsExtent * ctx.dragExtent.sign ),
234+ end: ctx.createOffset (ctx.totalActionsExtent * ctx.dragSign ),
235235 ).animate (ctx.controller);
236236
237237 return new Positioned .fill (
@@ -375,12 +375,12 @@ class SlidableDrawerDelegate extends SlidableStackDelegate {
375375///
376376/// By sliding in one of these direction, slide actions will appear.
377377class Slidable extends StatefulWidget {
378- /// Creates a widget that can be dismissed .
378+ /// Creates a widget that can be slid .
379379 ///
380380 /// The [actions] contains the slide actions that appears when the child has been dragged down or to the right.
381381 /// The [secondaryActions] contains the slide actions that appears when the child has been dragged up or to the left.
382382 ///
383- /// The [delegate] argument must not be null. The [actionExtentRatio]
383+ /// The [delegate] and [closeOnScroll] arguments must not be null. The [actionExtentRatio]
384384 /// and [showAllActionsThreshold] arguments must be greater or equal than 0 and less or equal than 1.
385385 Slidable ({
386386 Key key,
@@ -392,6 +392,7 @@ class Slidable extends StatefulWidget {
392392 double actionExtentRatio = _kActionsExtentRatio,
393393 Duration movementDuration = const Duration (milliseconds: 200 ),
394394 Axis direction = Axis .horizontal,
395+ bool closeOnScroll = true ,
395396 }) : this .builder (
396397 key: key,
397398 child: child,
@@ -402,8 +403,16 @@ class Slidable extends StatefulWidget {
402403 actionExtentRatio: actionExtentRatio,
403404 movementDuration: movementDuration,
404405 direction: direction,
406+ closeOnScroll: closeOnScroll,
405407 );
406408
409+ /// Creates a widget that can be slid.
410+ ///
411+ /// The [actionDelegate] is a delegate that builds the slide actions that appears when the child has been dragged down or to the right.
412+ /// The [secondaryActionDelegate] is a delegate that builds the slide actions that appears when the child has been dragged up or to the left.
413+ ///
414+ /// The [delegate] and [closeOnScroll] arguments must not be null. The [actionExtentRatio]
415+ /// and [showAllActionsThreshold] arguments must be greater or equal than 0 and less or equal than 1.
407416 Slidable .builder ({
408417 Key key,
409418 @required this .child,
@@ -414,11 +423,13 @@ class Slidable extends StatefulWidget {
414423 this .actionExtentRatio = _kActionsExtentRatio,
415424 this .movementDuration = const Duration (milliseconds: 200 ),
416425 this .direction = Axis .horizontal,
426+ this .closeOnScroll = true ,
417427 }) : assert (delegate != null ),
418428 assert (direction != null ),
419429 assert (showAllActionsThreshold != null && showAllActionsThreshold >= .0 && showAllActionsThreshold <= 1.0 ,
420430 'showAllActionsThreshold must be between 0.0 and 1.0' ),
421431 assert (actionExtentRatio != null && actionExtentRatio >= .0 && actionExtentRatio <= 1.0 , 'actionExtentRatio must be between 0.0 and 1.0' ),
432+ assert (closeOnScroll != null ),
422433 super (key: key);
423434
424435 /// The widget below this widget in the tree.
@@ -451,6 +462,11 @@ class Slidable extends StatefulWidget {
451462 /// Defines the duration for card to go to final position or to come back to original position if threshold not reached.
452463 final Duration movementDuration;
453464
465+ /// Specifies to close this slidable after the closest [Scrollable] 's position changed.
466+ ///
467+ /// Defaults to true.
468+ final bool closeOnScroll;
469+
454470 /// The state from the closest instance of this class that encloses the given context.
455471 static SlidableState of (BuildContext context) {
456472 return context.ancestorStateOfType (const TypeMatcher <SlidableState >());
@@ -471,6 +487,8 @@ class SlidableState extends State<Slidable> with TickerProviderStateMixin, Autom
471487
472488 double _dragExtent = 0.0 ;
473489
490+ ScrollPosition _scrollPosition;
491+
474492 bool get _showActions {
475493 return _dragExtent > 0 ;
476494 }
@@ -489,9 +507,40 @@ class SlidableState extends State<Slidable> with TickerProviderStateMixin, Autom
489507 return (_directionIsXAxis ? context.size.width : context.size.height) * widget.actionExtentRatio * (actionDelegate? .actionCount ?? 0 );
490508 }
491509
510+ @override
511+ void didChangeDependencies () {
512+ super .didChangeDependencies ();
513+ _removeScrollingNotifierListener ();
514+ _addScrollingNotifierListener ();
515+ }
516+
517+ @override
518+ void didUpdateWidget (Slidable oldWidget) {
519+ super .didUpdateWidget (oldWidget);
520+
521+ if (widget.closeOnScroll != oldWidget.closeOnScroll) {
522+ _removeScrollingNotifierListener ();
523+ _addScrollingNotifierListener ();
524+ }
525+ }
526+
527+ void _addScrollingNotifierListener () {
528+ if (widget.closeOnScroll) {
529+ _scrollPosition = Scrollable .of (context)? .position;
530+ if (_scrollPosition != null ) _scrollPosition.isScrollingNotifier.addListener (_isScrollingListener);
531+ }
532+ }
533+
534+ void _removeScrollingNotifierListener () {
535+ if (_scrollPosition != null ) {
536+ _scrollPosition.isScrollingNotifier.removeListener (_isScrollingListener);
537+ }
538+ }
539+
492540 @override
493541 void dispose () {
494542 _controller.dispose ();
543+ _removeScrollingNotifierListener ();
495544 super .dispose ();
496545 }
497546
@@ -503,6 +552,15 @@ class SlidableState extends State<Slidable> with TickerProviderStateMixin, Autom
503552 _controller.fling (velocity: - 1.0 );
504553 }
505554
555+ void _isScrollingListener () {
556+ if (! widget.closeOnScroll || _scrollPosition == null ) return ;
557+
558+ // When a scroll starts close this.
559+ if (_scrollPosition.isScrollingNotifier.value) {
560+ close ();
561+ }
562+ }
563+
506564 void _handleDragStart (DragStartDetails details) {
507565 _dragExtent = _controller.value * _overallDragAxisExtent * _dragExtent.sign;
508566 if (_controller.isAnimating) {
@@ -555,7 +613,7 @@ class SlidableState extends State<Slidable> with TickerProviderStateMixin, Autom
555613 new SlidableDelegateContext (
556614 widget,
557615 _showActions,
558- _dragExtent,
616+ _dragExtent.sign ,
559617 _controller,
560618 ),
561619 );
0 commit comments