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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| onEnd | - | Called when there is no Widget left to be swiped away | false
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ packages:
|
||||||
path: ".."
|
path: ".."
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.2.1"
|
version: "2.0.0"
|
||||||
js:
|
js:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
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
|
/// set to false if you want your card to move only across the horizontal axis when swiping
|
||||||
final bool isVerticalSwipingEnabled;
|
final bool isVerticalSwipingEnabled;
|
||||||
|
|
||||||
|
/// set to true if the stack should loop
|
||||||
|
final bool isLoop;
|
||||||
|
|
||||||
const CardSwiper({
|
const CardSwiper({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.cards,
|
required this.cards,
|
||||||
|
|
@ -64,6 +67,7 @@ class CardSwiper<T extends Widget> extends StatefulWidget {
|
||||||
this.direction = CardSwiperDirection.right,
|
this.direction = CardSwiperDirection.right,
|
||||||
this.isHorizontalSwipingEnabled = true,
|
this.isHorizontalSwipingEnabled = true,
|
||||||
this.isVerticalSwipingEnabled = true,
|
this.isVerticalSwipingEnabled = true,
|
||||||
|
this.isLoop = true,
|
||||||
}) : assert(
|
}) : assert(
|
||||||
maxAngle >= 0 && maxAngle <= 360,
|
maxAngle >= 0 && maxAngle <= 360,
|
||||||
'maxAngle must be between 0 and 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;
|
late double _scale = widget.scale;
|
||||||
double _difference = 40;
|
double _difference = 40;
|
||||||
|
|
||||||
int _currentIndex = 0;
|
|
||||||
|
|
||||||
SwipeType _swipeType = SwipeType.none;
|
SwipeType _swipeType = SwipeType.none;
|
||||||
bool _tapOnTop = false; //position of starting drag point on card
|
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> _scaleAnimation;
|
||||||
late Animation<double> _differenceAnimation;
|
late Animation<double> _differenceAnimation;
|
||||||
|
|
||||||
|
final List<T> _stack = [];
|
||||||
|
|
||||||
CardSwiperDirection detectedDirection = CardSwiperDirection.none;
|
CardSwiperDirection detectedDirection = CardSwiperDirection.none;
|
||||||
|
|
||||||
double get _maxAngle => widget.maxAngle * (pi / 180);
|
double get _maxAngle => widget.maxAngle * (pi / 180);
|
||||||
|
|
||||||
bool get _isLastCard => _currentIndex == widget.cards.length - 1;
|
int get _currentIndex => _stack.length - 1;
|
||||||
int get _nextCardIndex => _isLastCard ? 0 : _currentIndex + 1;
|
bool get _canSwipe => _stack.isNotEmpty && !widget.isDisabled;
|
||||||
|
bool get _hasBackItem => _stack.length > 1 || widget.isLoop;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
_stack.addAll(widget.cards);
|
||||||
|
|
||||||
widget.controller?.addListener(_controllerListener);
|
widget.controller?.addListener(_controllerListener);
|
||||||
|
|
||||||
_animationController = AnimationController(
|
_animationController = AnimationController(
|
||||||
|
|
@ -146,8 +153,8 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
fit: StackFit.expand,
|
fit: StackFit.expand,
|
||||||
children: [
|
children: [
|
||||||
_backItem(constraints),
|
if (_hasBackItem) _backItem(constraints),
|
||||||
_frontItem(constraints),
|
if (_stack.isNotEmpty) _frontItem(constraints),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -199,7 +206,7 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onPanEnd: (tapInfo) {
|
onPanEnd: (tapInfo) {
|
||||||
if (!widget.isDisabled) {
|
if (_canSwipe) {
|
||||||
_tapOnTop = false;
|
_tapOnTop = false;
|
||||||
_onEndAnimation();
|
_onEndAnimation();
|
||||||
_animationController.forward();
|
_animationController.forward();
|
||||||
|
|
@ -217,7 +224,9 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
|
||||||
scale: _scale,
|
scale: _scale,
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: constraints,
|
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(() {
|
setState(() {
|
||||||
if (_swipeType == SwipeType.swipe) {
|
if (_swipeType == SwipeType.swipe) {
|
||||||
widget.onSwipe?.call(_currentIndex, detectedDirection);
|
widget.onSwipe?.call(_currentIndex, detectedDirection);
|
||||||
|
_stack.removeAt(_currentIndex);
|
||||||
|
|
||||||
if (_isLastCard) {
|
if (_stack.isEmpty) {
|
||||||
widget.onEnd?.call();
|
widget.onEnd?.call();
|
||||||
_currentIndex = 0;
|
|
||||||
} else {
|
if (widget.isLoop) {
|
||||||
_currentIndex++;
|
_stack.addAll(widget.cards);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_animationController.reset();
|
_animationController.reset();
|
||||||
|
|
@ -316,7 +327,7 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
|
||||||
}
|
}
|
||||||
|
|
||||||
void _swipe(BuildContext context, CardSwiperDirection direction) {
|
void _swipe(BuildContext context, CardSwiperDirection direction) {
|
||||||
if (widget.cards.isEmpty) return;
|
if (!_canSwipe) return;
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case CardSwiperDirection.left:
|
case CardSwiperDirection.left:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue