feat: add option to control if the stack should loop
This commit is contained in:
parent
4a8ea3afcf
commit
5f71cf9b4d
|
|
@ -105,6 +105,7 @@ class Example extends StatelessWidget {
|
|||
| isDisabled | false | Set to ```true``` if swiping should be disabled, has no impact when triggered from the outside | false
|
||||
| isHorizontalSwipingEnabled | true | Set to ```false``` if you want your card to move only across the vertical axis when swiping | false
|
||||
| isVerticalSwipingEnabled | true | Set to ```false``` if you want your card to move only across the horizontal axis when swiping | false
|
||||
| isLoop | true | set to ```true``` if the stack should loop | false
|
||||
| onTapDisabled | - | Function that get triggered when the swiper is disabled | false
|
||||
| onSwipe | - | Called with the new index and detected swipe direction when the user swiped | false
|
||||
| onEnd | - | Called when there is no Widget left to be swiped away | false
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ packages:
|
|||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.2.1"
|
||||
version: "2.0.0"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -48,6 +48,9 @@ class CardSwiper<T extends Widget> extends StatefulWidget {
|
|||
/// set to false if you want your card to move only across the horizontal axis when swiping
|
||||
final bool isVerticalSwipingEnabled;
|
||||
|
||||
/// set to true if the stack should loop
|
||||
final bool isLoop;
|
||||
|
||||
const CardSwiper({
|
||||
Key? key,
|
||||
required this.cards,
|
||||
|
|
@ -64,6 +67,7 @@ class CardSwiper<T extends Widget> extends StatefulWidget {
|
|||
this.direction = CardSwiperDirection.right,
|
||||
this.isHorizontalSwipingEnabled = true,
|
||||
this.isVerticalSwipingEnabled = true,
|
||||
this.isLoop = true,
|
||||
}) : assert(
|
||||
maxAngle >= 0 && maxAngle <= 360,
|
||||
'maxAngle must be between 0 and 360',
|
||||
|
|
@ -95,8 +99,6 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
|
|||
late double _scale = widget.scale;
|
||||
double _difference = 40;
|
||||
|
||||
int _currentIndex = 0;
|
||||
|
||||
SwipeType _swipeType = SwipeType.none;
|
||||
bool _tapOnTop = false; //position of starting drag point on card
|
||||
|
||||
|
|
@ -106,17 +108,22 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
|
|||
late Animation<double> _scaleAnimation;
|
||||
late Animation<double> _differenceAnimation;
|
||||
|
||||
final List<T> _stack = [];
|
||||
|
||||
CardSwiperDirection detectedDirection = CardSwiperDirection.none;
|
||||
|
||||
double get _maxAngle => widget.maxAngle * (pi / 180);
|
||||
|
||||
bool get _isLastCard => _currentIndex == widget.cards.length - 1;
|
||||
int get _nextCardIndex => _isLastCard ? 0 : _currentIndex + 1;
|
||||
int get _currentIndex => _stack.length - 1;
|
||||
bool get _canSwipe => _stack.isNotEmpty && !widget.isDisabled;
|
||||
bool get _hasBackItem => _stack.length > 1 || widget.isLoop;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_stack.addAll(widget.cards);
|
||||
|
||||
widget.controller?.addListener(_controllerListener);
|
||||
|
||||
_animationController = AnimationController(
|
||||
|
|
@ -146,8 +153,8 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
|
|||
clipBehavior: Clip.none,
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
_backItem(constraints),
|
||||
_frontItem(constraints),
|
||||
if (_hasBackItem) _backItem(constraints),
|
||||
if (_stack.isNotEmpty) _frontItem(constraints),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
|
@ -199,7 +206,7 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
|
|||
}
|
||||
},
|
||||
onPanEnd: (tapInfo) {
|
||||
if (!widget.isDisabled) {
|
||||
if (_canSwipe) {
|
||||
_tapOnTop = false;
|
||||
_onEndAnimation();
|
||||
_animationController.forward();
|
||||
|
|
@ -217,7 +224,9 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
|
|||
scale: _scale,
|
||||
child: ConstrainedBox(
|
||||
constraints: constraints,
|
||||
child: widget.cards[_nextCardIndex],
|
||||
child: _stack.length <= 1
|
||||
? widget.cards.last
|
||||
: widget.cards[_currentIndex - 1],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -264,12 +273,14 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
|
|||
setState(() {
|
||||
if (_swipeType == SwipeType.swipe) {
|
||||
widget.onSwipe?.call(_currentIndex, detectedDirection);
|
||||
_stack.removeAt(_currentIndex);
|
||||
|
||||
if (_isLastCard) {
|
||||
if (_stack.isEmpty) {
|
||||
widget.onEnd?.call();
|
||||
_currentIndex = 0;
|
||||
} else {
|
||||
_currentIndex++;
|
||||
|
||||
if (widget.isLoop) {
|
||||
_stack.addAll(widget.cards);
|
||||
}
|
||||
}
|
||||
}
|
||||
_animationController.reset();
|
||||
|
|
@ -316,7 +327,7 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
|
|||
}
|
||||
|
||||
void _swipe(BuildContext context, CardSwiperDirection direction) {
|
||||
if (widget.cards.isEmpty) return;
|
||||
if (!_canSwipe) return;
|
||||
|
||||
switch (direction) {
|
||||
case CardSwiperDirection.left:
|
||||
|
|
|
|||
Loading…
Reference in New Issue