forked from inex/swipe_to_action
Add max offset listener
This commit is contained in:
parent
976427f9df
commit
a6ae48da8b
|
@ -19,6 +19,8 @@ typedef SwipeDirectionCallback = void Function(SwipeDirection direction);
|
||||||
/// Used by [Swipeable.confirmSwipe].
|
/// Used by [Swipeable.confirmSwipe].
|
||||||
typedef ConfirmSwipeCallback = Future<bool> Function(SwipeDirection direction);
|
typedef ConfirmSwipeCallback = Future<bool> Function(SwipeDirection direction);
|
||||||
|
|
||||||
|
typedef OnOverScrollTheMaxOffset = void Function();
|
||||||
|
|
||||||
/// The direction in which a [Swipeable] can be swiped.
|
/// The direction in which a [Swipeable] can be swiped.
|
||||||
enum SwipeDirection {
|
enum SwipeDirection {
|
||||||
/// The [Swipeable] can be swiped by dragging either left or right.
|
/// 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.movementDuration = const Duration(milliseconds: 200),
|
||||||
this.crossAxisEndOffset = 0.0,
|
this.crossAxisEndOffset = 0.0,
|
||||||
this.dragStartBehavior = DragStartBehavior.start,
|
this.dragStartBehavior = DragStartBehavior.start,
|
||||||
|
this.swipeIntensity = 1.0,
|
||||||
this.allowedPointerKinds = const {
|
this.allowedPointerKinds = const {
|
||||||
PointerDeviceKind.invertedStylus,
|
PointerDeviceKind.invertedStylus,
|
||||||
PointerDeviceKind.stylus,
|
PointerDeviceKind.stylus,
|
||||||
PointerDeviceKind.touch
|
PointerDeviceKind.touch
|
||||||
},
|
},
|
||||||
|
this.onOverScrollTheMaxOffset,
|
||||||
}) : assert(secondaryBackground == null || background != null),
|
}) : assert(secondaryBackground == null || background != null),
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
|
@ -154,6 +158,13 @@ class Swipeable extends StatefulWidget {
|
||||||
/// * [DragGestureRecognizer.dragStartBehavior], which gives an example for the different behaviors.
|
/// * [DragGestureRecognizer.dragStartBehavior], which gives an example for the different behaviors.
|
||||||
final DragStartBehavior dragStartBehavior;
|
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
|
@override
|
||||||
_SwipeableState createState() => _SwipeableState();
|
_SwipeableState createState() => _SwipeableState();
|
||||||
}
|
}
|
||||||
|
@ -191,6 +202,19 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin, Au
|
||||||
_moveController = AnimationController(duration: widget.movementDuration, vsync: this)
|
_moveController = AnimationController(duration: widget.movementDuration, vsync: this)
|
||||||
..addStatusListener(_handleDismissStatusChanged);
|
..addStatusListener(_handleDismissStatusChanged);
|
||||||
_updateMoveAnimation();
|
_updateMoveAnimation();
|
||||||
|
_moveController.addListener(() {
|
||||||
|
|
||||||
|
if (!isInSwipe) {
|
||||||
|
isSwipeAnimationRunning = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSwipeAnimationRunning && _moveController.value >= widget.maxOffset) {
|
||||||
|
if (widget.onOverScrollTheMaxOffset != null) {
|
||||||
|
widget.onOverScrollTheMaxOffset!();
|
||||||
|
}
|
||||||
|
isSwipeAnimationRunning = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
@ -199,6 +223,7 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin, Au
|
||||||
late Animation<Offset> _moveAnimation;
|
late Animation<Offset> _moveAnimation;
|
||||||
|
|
||||||
double _dragExtent = 0.0;
|
double _dragExtent = 0.0;
|
||||||
|
bool isSwipeAnimationRunning = false;
|
||||||
bool _dragUnderway = false;
|
bool _dragUnderway = false;
|
||||||
Size? _sizePriorToCollapse;
|
Size? _sizePriorToCollapse;
|
||||||
|
|
||||||
|
@ -207,6 +232,8 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin, Au
|
||||||
@override
|
@override
|
||||||
bool get wantKeepAlive => _moveController.isAnimating == true;
|
bool get wantKeepAlive => _moveController.isAnimating == true;
|
||||||
|
|
||||||
|
bool get isInSwipe => _moveController.value != 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_moveController.dispose();
|
_moveController.dispose();
|
||||||
|
@ -261,7 +288,7 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin, Au
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final delta = details.primaryDelta ?? 0.0;
|
final delta = (details.primaryDelta ?? 0.0) * widget.swipeIntensity;
|
||||||
final oldDragExtent = _dragExtent;
|
final oldDragExtent = _dragExtent;
|
||||||
switch (widget.direction) {
|
switch (widget.direction) {
|
||||||
case SwipeDirection.none:
|
case SwipeDirection.none:
|
||||||
|
@ -351,7 +378,7 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin, Au
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_dragUnderway = false;
|
_dragUnderway = false;
|
||||||
if (_moveController.isCompleted && await _confirmStartSwipeAnimation() == true) {
|
if (_moveController.value >= widget.maxOffset && await _confirmStartSwipeAnimation() == true) {
|
||||||
_startSwipeAnimation();
|
_startSwipeAnimation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -375,12 +402,7 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin, Au
|
||||||
break;
|
break;
|
||||||
case _FlingGestureKind.none:
|
case _FlingGestureKind.none:
|
||||||
if (!_moveController.isDismissed) {
|
if (!_moveController.isDismissed) {
|
||||||
// we already know it's not completed, we check that above
|
await _moveController.reverse();
|
||||||
if (_moveController.value > (widget.dismissThresholds[_swipeDirection] ?? _kDismissThreshold)) {
|
|
||||||
await _moveController.forward();
|
|
||||||
} else {
|
|
||||||
await _moveController.reverse();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -406,7 +428,6 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin, Au
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startSwipeAnimation() {
|
void _startSwipeAnimation() {
|
||||||
assert(_moveController.isCompleted);
|
|
||||||
assert(_sizePriorToCollapse == null);
|
assert(_sizePriorToCollapse == null);
|
||||||
|
|
||||||
final direction = _swipeDirection;
|
final direction = _swipeDirection;
|
||||||
|
|
Loading…
Reference in a new issue