From a6ae48da8b2511856e6334caa6a3ab459afd1aa0 Mon Sep 17 00:00:00 2001 From: sherlock Date: Fri, 4 Aug 2023 14:11:32 +0700 Subject: [PATCH] Add max offset listener --- lib/src/swipeable.dart | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/lib/src/swipeable.dart b/lib/src/swipeable.dart index 021faec..c91e5b3 100644 --- a/lib/src/swipeable.dart +++ b/lib/src/swipeable.dart @@ -19,6 +19,8 @@ typedef SwipeDirectionCallback = void Function(SwipeDirection direction); /// Used by [Swipeable.confirmSwipe]. typedef ConfirmSwipeCallback = Future Function(SwipeDirection direction); +typedef OnOverScrollTheMaxOffset = void Function(); + /// The direction in which a [Swipeable] can be swiped. enum SwipeDirection { /// The [Swipeable] can be swiped by dragging either left or right. @@ -58,11 +60,13 @@ class Swipeable extends StatefulWidget { this.movementDuration = const Duration(milliseconds: 200), this.crossAxisEndOffset = 0.0, this.dragStartBehavior = DragStartBehavior.start, + this.swipeIntensity = 1.0, this.allowedPointerKinds = const { PointerDeviceKind.invertedStylus, PointerDeviceKind.stylus, PointerDeviceKind.touch }, + this.onOverScrollTheMaxOffset, }) : assert(secondaryBackground == null || background != null), super(key: key); @@ -154,6 +158,13 @@ class Swipeable extends StatefulWidget { /// * [DragGestureRecognizer.dragStartBehavior], which gives an example for the different behaviors. final DragStartBehavior dragStartBehavior; + ///If the swipeIntensity is low, the message requires a stronger swipe. + ///The default value is set to 1. Consider increasing the swipeIntensity to make it easier for users to swipe. + final double swipeIntensity; + + /// When the user scrolls beyond the maximum offset, the function will be invoked, and it will only be called once. + final OnOverScrollTheMaxOffset? onOverScrollTheMaxOffset; + @override _SwipeableState createState() => _SwipeableState(); } @@ -191,6 +202,19 @@ class _SwipeableState extends State with TickerProviderStateMixin, Au _moveController = AnimationController(duration: widget.movementDuration, vsync: this) ..addStatusListener(_handleDismissStatusChanged); _updateMoveAnimation(); + _moveController.addListener(() { + + if (!isInSwipe) { + isSwipeAnimationRunning = true; + } + + if (isSwipeAnimationRunning && _moveController.value >= widget.maxOffset) { + if (widget.onOverScrollTheMaxOffset != null) { + widget.onOverScrollTheMaxOffset!(); + } + isSwipeAnimationRunning = false; + } + }); super.initState(); } @@ -199,6 +223,7 @@ class _SwipeableState extends State with TickerProviderStateMixin, Au late Animation _moveAnimation; double _dragExtent = 0.0; + bool isSwipeAnimationRunning = false; bool _dragUnderway = false; Size? _sizePriorToCollapse; @@ -207,6 +232,8 @@ class _SwipeableState extends State with TickerProviderStateMixin, Au @override bool get wantKeepAlive => _moveController.isAnimating == true; + bool get isInSwipe => _moveController.value != 0; + @override void dispose() { _moveController.dispose(); @@ -261,7 +288,7 @@ class _SwipeableState extends State with TickerProviderStateMixin, Au return; } - final delta = details.primaryDelta ?? 0.0; + final delta = (details.primaryDelta ?? 0.0) * widget.swipeIntensity; final oldDragExtent = _dragExtent; switch (widget.direction) { case SwipeDirection.none: @@ -351,7 +378,7 @@ class _SwipeableState extends State with TickerProviderStateMixin, Au return; } _dragUnderway = false; - if (_moveController.isCompleted && await _confirmStartSwipeAnimation() == true) { + if (_moveController.value >= widget.maxOffset && await _confirmStartSwipeAnimation() == true) { _startSwipeAnimation(); return; } @@ -375,12 +402,7 @@ class _SwipeableState extends State with TickerProviderStateMixin, Au break; case _FlingGestureKind.none: if (!_moveController.isDismissed) { - // we already know it's not completed, we check that above - if (_moveController.value > (widget.dismissThresholds[_swipeDirection] ?? _kDismissThreshold)) { - await _moveController.forward(); - } else { - await _moveController.reverse(); - } + await _moveController.reverse(); } break; } @@ -406,7 +428,6 @@ class _SwipeableState extends State with TickerProviderStateMixin, Au } void _startSwipeAnimation() { - assert(_moveController.isCompleted); assert(_sizePriorToCollapse == null); final direction = _swipeDirection; @@ -428,7 +449,7 @@ class _SwipeableState extends State with TickerProviderStateMixin, Au background = widget.secondaryBackground; } } - + Widget content = SlideTransition( position: _moveAnimation, child: widget.child,