feature: display more cards behind the first one (#6)

This commit is contained in:
giboin 2023-03-18 18:43:24 +01:00 committed by GitHub
parent 6e40955758
commit a8cbd3a110
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 7 deletions

View File

@ -1,3 +1,7 @@
## [2.1.0]
- Add option to display more cards at a time. Useful if the widgets you want in your cards take time to build (for example a network image or video): displaying more cards builds them in advance and makes a fast serie of swipes more fluid.
## [2.0.1] ## [2.0.1]
- Fixes wrong item rendering. - Fixes wrong item rendering.

View File

@ -110,6 +110,7 @@ class Example extends StatelessWidget {
| 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
| direction | right | Direction in which the card is swiped away when triggered from the outside | false | direction | right | Direction in which the card is swiped away when triggered from the outside | false
| numberOfCardsDisplayed | 2 | If your widgets in the 'cards' list cause performance issues, you can choose to display more cards at a time to reduce how long the user waits for a card to appear | false
#### Controller #### Controller

View File

@ -36,6 +36,7 @@ class _ExamplePageState extends State<Example> {
child: CardSwiper( child: CardSwiper(
controller: controller, controller: controller,
cards: cards, cards: cards,
numberOfCardsDisplayed: 3,
onSwipe: _swipe, onSwipe: _swipe,
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
), ),

View File

@ -51,6 +51,9 @@ class CardSwiper<T extends Widget> extends StatefulWidget {
/// set to true if the stack should loop /// set to true if the stack should loop
final bool isLoop; final bool isLoop;
/// here you can change the number of cards that are displayed at the same time
final int numberOfCardsDisplayed;
const CardSwiper({ const CardSwiper({
Key? key, Key? key,
required this.cards, required this.cards,
@ -68,6 +71,7 @@ class CardSwiper<T extends Widget> extends StatefulWidget {
this.isHorizontalSwipingEnabled = true, this.isHorizontalSwipingEnabled = true,
this.isVerticalSwipingEnabled = true, this.isVerticalSwipingEnabled = true,
this.isLoop = true, this.isLoop = true,
this.numberOfCardsDisplayed = 2,
}) : assert( }) : assert(
maxAngle >= 0 && maxAngle <= 360, maxAngle >= 0 && maxAngle <= 360,
'maxAngle must be between 0 and 360', 'maxAngle must be between 0 and 360',
@ -84,6 +88,10 @@ class CardSwiper<T extends Widget> extends StatefulWidget {
scale >= 0 && scale <= 1, scale >= 0 && scale <= 1,
'scale must be between 0 and 1', 'scale must be between 0 and 1',
), ),
assert(
numberOfCardsDisplayed >= 1 && numberOfCardsDisplayed <= cards.length,
'you must display at least one card, and no more than the length of cards parameter',
),
super(key: key); super(key: key);
@override @override
@ -116,7 +124,6 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
int get _currentIndex => _stack.length - 1; int get _currentIndex => _stack.length - 1;
bool get _canSwipe => _stack.isNotEmpty && !widget.isDisabled; bool get _canSwipe => _stack.isNotEmpty && !widget.isDisabled;
bool get _hasBackItem => _stack.length > 1 || widget.isLoop;
@override @override
void initState() { void initState() {
@ -152,10 +159,15 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
return Stack( return Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,
fit: StackFit.expand, fit: StackFit.expand,
children: [ children: List.generate(nbOfCardsOnScreen(), (index) {
if (_hasBackItem) _backItem(constraints), if (index == 0) {
if (_stack.isNotEmpty) _frontItem(constraints), return _frontItem(constraints);
], }
if (index == 1) {
return _secondItem(constraints);
}
return _backItem(constraints, index);
}).reversed.toList(),
); );
}, },
), ),
@ -164,6 +176,19 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
); );
} }
///the number of cards that are built on the screen
int nbOfCardsOnScreen() {
return widget.isLoop
? widget.numberOfCardsDisplayed
: _stack.isNotEmpty
? min(
widget.numberOfCardsDisplayed,
_stack.length,
)
: 0;
}
/// The card shown at the front of the stack, that can be dragged and swipped
Widget _frontItem(BoxConstraints constraints) { Widget _frontItem(BoxConstraints constraints) {
return Positioned( return Positioned(
left: _left, left: _left,
@ -216,7 +241,9 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
); );
} }
Widget _backItem(BoxConstraints constraints) { /// the card that is just behind the _frontItem, only moves to take its place
/// during a movement of _frontItem
Widget _secondItem(BoxConstraints constraints) {
return Positioned( return Positioned(
top: _difference, top: _difference,
left: 0, left: 0,
@ -227,6 +254,23 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper<T>>
child: _stack.length <= 1 child: _stack.length <= 1
? widget.cards.last ? widget.cards.last
: _stack[_currentIndex - 1], : _stack[_currentIndex - 1],
//or: widget.cards[(_currentIndex - 1) % widget.cards.length] (same thing)
),
),
);
}
/// if widget.numberOfCardsDisplayed > 2, those cards are built behind the
/// _secondItem and can't move at all
Widget _backItem(BoxConstraints constraints, int index) {
return Positioned(
top: 40,
left: 0,
child: Transform.scale(
scale: widget.scale,
child: ConstrainedBox(
constraints: constraints,
child: widget.cards[(_currentIndex - index) % widget.cards.length],
), ),
), ),
); );

View File

@ -2,7 +2,7 @@ name: flutter_card_swiper
description: This is a Tinder-like card swiper package. It allows you to swipe left, right, up, and down and define your own business logic for each direction. description: This is a Tinder-like card swiper package. It allows you to swipe left, right, up, and down and define your own business logic for each direction.
homepage: https://github.com/ricardodalarme/flutter_card_swiper homepage: https://github.com/ricardodalarme/flutter_card_swiper
issue_tracker: https://github.com/ricardodalarme/flutter_card_swiper/issues issue_tracker: https://github.com/ricardodalarme/flutter_card_swiper/issues
version: 2.0.1 version: 2.1.0
environment: environment:
sdk: ">=2.12.0 <3.0.0" sdk: ">=2.12.0 <3.0.0"