feat: add support for handling negative backCardOffset

This commit is contained in:
Jawwad Hassan 2023-05-04 16:03:41 +05:00
parent efed38b755
commit 347c9fdcd5
2 changed files with 39 additions and 38 deletions

View File

@ -1,9 +1,8 @@
import 'dart:math'; import 'dart:math' as math;
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_card_swiper/flutter_card_swiper.dart'; import 'package:flutter_card_swiper/flutter_card_swiper.dart';
import 'package:flutter_card_swiper/src/extensions.dart';
class CardAnimation { class CardAnimation {
CardAnimation({ CardAnimation({
@ -13,8 +12,7 @@ class CardAnimation {
required this.initialOffset, required this.initialOffset,
this.isHorizontalSwipingEnabled = true, this.isHorizontalSwipingEnabled = true,
this.isVerticalSwipingEnabled = true, this.isVerticalSwipingEnabled = true,
}) : scale = initialScale, }) : scale = initialScale;
difference = initialOffset;
final double maxAngle; final double maxAngle;
final double initialScale; final double initialScale;
@ -28,14 +26,14 @@ class CardAnimation {
double total = 0; double total = 0;
double angle = 0; double angle = 0;
double scale; double scale;
Offset difference; Offset difference = Offset.zero;
late Animation<double> _leftAnimation; late Animation<double> _leftAnimation;
late Animation<double> _topAnimation; late Animation<double> _topAnimation;
late Animation<double> _scaleAnimation; late Animation<double> _scaleAnimation;
late Animation<Offset> _differenceAnimation; late Animation<Offset> _differenceAnimation;
double get _maxAngleInRadian => maxAngle * (pi / 180); double get _maxAngleInRadian => maxAngle * (math.pi / 180);
void sync() { void sync() {
left = _leftAnimation.value; left = _leftAnimation.value;
@ -51,7 +49,7 @@ class CardAnimation {
total = 0; total = 0;
angle = 0; angle = 0;
scale = initialScale; scale = initialScale;
difference = initialOffset; difference = Offset.zero;
} }
void update(double dx, double dy, bool inverseAngle) { void update(double dx, double dy, bool inverseAngle) {
@ -68,27 +66,36 @@ class CardAnimation {
} }
void updateAngle(bool inverse) { void updateAngle(bool inverse) {
if (angle.isBetween(-_maxAngleInRadian, _maxAngleInRadian)) { angle = clampDouble(
angle = _maxAngleInRadian * left / 1000; _maxAngleInRadian * left / 1000,
if (inverse) angle *= -1; -_maxAngleInRadian,
} _maxAngleInRadian,
);
if (inverse) angle *= -1;
} }
void updateScale() { void updateScale() {
scale = (total > 0) scale = clampDouble(initialScale + (total.abs() / 5000), initialScale, 1.0);
? clampDouble(initialScale + (total / 5000), initialScale, 1.0)
: clampDouble(initialScale - (total / 5000), initialScale, 1.0);
} }
void updateDifference() { void updateDifference() {
final discrepancy = (total > 0) ? total / 10 : -(total / 10); final discrepancy = (total / 10).abs();
if (difference.dx.isBetween(0, initialOffset.dx)) { var diffX = 0.0, diffY = 0.0;
difference = Offset(initialOffset.dx + discrepancy, difference.dy);
if (initialOffset.dx > 0) {
diffX = discrepancy;
} else if (initialOffset.dx < 0) {
diffX = -discrepancy;
} }
if (difference.dy.isBetween(0, initialOffset.dy)) {
difference = Offset(difference.dx, initialOffset.dy + discrepancy); if (initialOffset.dy < 0) {
diffY = -discrepancy;
} else if (initialOffset.dy > 0) {
diffY = discrepancy;
} }
difference = Offset(diffX, diffY);
} }
void animate(BuildContext context, CardSwiperDirection direction) { void animate(BuildContext context, CardSwiperDirection direction) {
@ -123,7 +130,7 @@ class CardAnimation {
).animate(animationController); ).animate(animationController);
_differenceAnimation = Tween<Offset>( _differenceAnimation = Tween<Offset>(
begin: difference, begin: difference,
end: Offset.zero, end: initialOffset,
).animate(animationController); ).animate(animationController);
animationController.forward(); animationController.forward();
} }
@ -145,7 +152,7 @@ class CardAnimation {
).animate(animationController); ).animate(animationController);
_differenceAnimation = Tween<Offset>( _differenceAnimation = Tween<Offset>(
begin: difference, begin: difference,
end: Offset.zero, end: initialOffset,
).animate(animationController); ).animate(animationController);
animationController.forward(); animationController.forward();
} }
@ -165,7 +172,7 @@ class CardAnimation {
).animate(animationController); ).animate(animationController);
_differenceAnimation = Tween<Offset>( _differenceAnimation = Tween<Offset>(
begin: difference, begin: difference,
end: initialOffset, end: Offset.zero,
).animate(animationController); ).animate(animationController);
animationController.forward(); animationController.forward();
} }
@ -201,7 +208,7 @@ class CardAnimation {
end: scale, end: scale,
).animate(animationController); ).animate(animationController);
_differenceAnimation = Tween<Offset>( _differenceAnimation = Tween<Offset>(
begin: Offset.zero, begin: initialOffset,
end: difference, end: difference,
).animate(animationController); ).animate(animationController);
animationController.forward(); animationController.forward();
@ -223,7 +230,7 @@ class CardAnimation {
end: scale, end: scale,
).animate(animationController); ).animate(animationController);
_differenceAnimation = Tween<Offset>( _differenceAnimation = Tween<Offset>(
begin: Offset.zero, begin: initialOffset,
end: difference, end: difference,
).animate(animationController); ).animate(animationController);
animationController.forward(); animationController.forward();

View File

@ -1,5 +1,5 @@
import 'dart:collection'; import 'dart:collection';
import 'dart:math'; import 'dart:math' as math;
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_card_swiper/src/card_animation.dart'; import 'package:flutter_card_swiper/src/card_animation.dart';
@ -157,10 +157,6 @@ class CardSwiper extends StatefulWidget {
initialIndex >= 0 && initialIndex < cardsCount, initialIndex >= 0 && initialIndex < cardsCount,
'initialIndex must be between 0 and [cardsCount]', 'initialIndex must be between 0 and [cardsCount]',
), ),
assert(
backCardOffset >= Offset.zero,
'backCardOffset must be a positive value',
),
super(key: key); super(key: key);
@override @override
@ -227,9 +223,7 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper>
clipBehavior: Clip.none, clipBehavior: Clip.none,
fit: StackFit.expand, fit: StackFit.expand,
children: List.generate(numberOfCardsOnScreen(), (index) { children: List.generate(numberOfCardsOnScreen(), (index) {
if (index == 0) { if (index == 0) return _frontItem(constraints);
return _frontItem(constraints);
}
return _backItem(constraints, index); return _backItem(constraints, index);
}).reversed.toList(), }).reversed.toList(),
@ -287,15 +281,15 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper>
); );
} }
Widget _backItem(BoxConstraints constraints, int offset) { Widget _backItem(BoxConstraints constraints, int index) {
return Positioned( return Positioned(
top: _cardAnimation.difference.dy * offset, top: (widget.backCardOffset.dy * index) - _cardAnimation.difference.dy,
left: _cardAnimation.difference.dx * offset, left: (widget.backCardOffset.dx * index) - _cardAnimation.difference.dx,
child: Transform.scale( child: Transform.scale(
scale: _cardAnimation.scale - ((1 - widget.scale) * (offset - 1)), scale: _cardAnimation.scale - ((1 - widget.scale) * (index - 1)),
child: ConstrainedBox( child: ConstrainedBox(
constraints: constraints, constraints: constraints,
child: widget.cardBuilder(context, getValidIndexOffset(offset)!), child: widget.cardBuilder(context, getValidIndexOffset(index)!),
), ),
), ),
); );
@ -426,7 +420,7 @@ class _CardSwiperState<T extends Widget> extends State<CardSwiper>
return 0; return 0;
} }
return min( return math.min(
widget.numberOfCardsDisplayed, widget.numberOfCardsDisplayed,
widget.cardsCount - _currentIndex!, widget.cardsCount - _currentIndex!,
); );