Reputation: 2792
i am using this plugin for swiping. one of the flow of the app is to,
but if i swipe up to view the profile it will remove the user from the list, which is not what i want...
i want it that, if i swipe up it should not remove from the list. i have try to disable swipe up but not navigating to profile page.
i have download the plugin to edit but i cant figure out where is removing from the list..
here is the plugin code
library flutter_tindercard;
import 'dart:math';
import 'package:flutter/material.dart';
enum TriggerDirection { none, right, left, up, down }
/// A Tinder-Like Widget.
class TinderSwapCard extends StatefulWidget {
final CardBuilder _cardBuilder;
final int _totalNum;
final int _stackNum;
final int _animDuration;
final double _swipeEdge;
final double _swipeEdgeVertical;
final bool _swipeUp;
final bool _swipeDown;
final bool _allowVerticalMovement;
final CardSwipeCompleteCallback? swipeCompleteCallback;
final CardDragUpdateCallback? swipeUpdateCallback;
final CardController? cardController;
final List<Size> _cardSizes = [];
final List<Alignment> _cardAligns = [];
@override
_TinderSwapCardState createState() => _TinderSwapCardState();
/// Constructor requires Card Widget Builder [cardBuilder] and
/// your card count [totalNum]
/// option includes:
/// stack orientation [orientation], number of card display
/// in same time [stackNum], [swipeEdge] is the edge to determine
/// action(recover or swipe) when you release your swiping card it is the
/// value of alignment, 0.0 means middle, so it need bigger than zero.
/// and size control params;
TinderSwapCard({
required CardBuilder cardBuilder,
required int totalNum,
AmassOrientation orientation = AmassOrientation.bottom,
int stackNum = 3,
int animDuration = 800,
double swipeEdge = 3.0,
double swipeEdgeVertical = 8.0,
bool swipeUp = false,
bool swipeDown = false,
double? maxWidth,
double? maxHeight,
double? minWidth,
double? minHeight,
bool allowVerticalMovement = true,
this.cardController,
this.swipeCompleteCallback,
this.swipeUpdateCallback,
}) : assert(stackNum > 1),
assert(swipeEdge > 0),
assert(swipeEdgeVertical > 0),
assert(maxWidth! > minWidth! && maxHeight! > minHeight!),
_cardBuilder = cardBuilder,
_totalNum = totalNum,
_stackNum = stackNum,
_animDuration = animDuration,
_swipeEdge = swipeEdge,
_swipeEdgeVertical = swipeEdgeVertical,
_swipeUp = swipeUp,
_swipeDown = swipeDown,
_allowVerticalMovement = allowVerticalMovement {
final widthGap = maxWidth! - minWidth!;
final heightGap = maxHeight! - minHeight!;
for (var i = 0; i < _stackNum; i++) {
_cardSizes.add(
Size(minWidth + (widthGap / _stackNum) * i,
minHeight + (heightGap / _stackNum) * i),
);
switch (orientation) {
case AmassOrientation.bottom:
_cardAligns.add(
Alignment(
0.0,
(0.5 / (_stackNum - 1)) * (stackNum - i),
),
);
break;
case AmassOrientation.top:
_cardAligns.add(
Alignment(
0.0,
(-0.5 / (_stackNum - 1)) * (stackNum - i),
),
);
break;
case AmassOrientation.left:
_cardAligns.add(
Alignment(
(-0.5 / (_stackNum - 1)) * (stackNum - i),
0.0,
),
);
break;
case AmassOrientation.right:
_cardAligns.add(
Alignment(
(0.5 / (_stackNum - 1)) * (stackNum - i),
0.0,
),
);
break;
}
}
}
}
class _TinderSwapCardState extends State<TinderSwapCard>
with TickerProviderStateMixin {
late Alignment frontCardAlign;
late AnimationController _animationController;
late int _currentFront;
static TriggerDirection? _trigger;
Widget _buildCard(BuildContext context, int realIndex) {
if (realIndex < 0) {
return Container();
}
final index = realIndex - _currentFront;
if (index == widget._stackNum - 1) {
return Align(
alignment: _animationController.status == AnimationStatus.forward
? frontCardAlign = CardAnimation.frontCardAlign(
_animationController,
frontCardAlign,
widget._cardAligns[widget._stackNum - 1],
widget._swipeEdge,
widget._swipeUp,
widget._swipeDown,
).value
: frontCardAlign,
child: Transform.rotate(
angle: (pi / 180.0) *
(_animationController.status == AnimationStatus.forward
? CardAnimation.frontCardRota(
_animationController, frontCardAlign.x)
.value
: frontCardAlign.x),
child: SizedBox.fromSize(
size: widget._cardSizes[index],
child: widget._cardBuilder(
context,
widget._totalNum - realIndex - 1,
),
),
),
);
}
return Align(
alignment: _animationController.status == AnimationStatus.forward &&
(frontCardAlign.x > 3.0 ||
frontCardAlign.x < -3.0 ||
frontCardAlign.y > 3 ||
frontCardAlign.y < -3)
? CardAnimation.backCardAlign(
_animationController,
widget._cardAligns[index],
widget._cardAligns[index + 1],
).value
: widget._cardAligns[index],
child: SizedBox.fromSize(
size: _animationController.status == AnimationStatus.forward &&
(frontCardAlign.x > 3.0 ||
frontCardAlign.x < -3.0 ||
frontCardAlign.y > 3 ||
frontCardAlign.y < -3)
? CardAnimation.backCardSize(
_animationController,
widget._cardSizes[index],
widget._cardSizes[index + 1],
).value
: widget._cardSizes[index],
child: widget._cardBuilder(
context,
widget._totalNum - realIndex - 1,
),
),
);
}
List<Widget> _buildCards(BuildContext context) {
final cards = <Widget>[];
for (var i = _currentFront; i < _currentFront + widget._stackNum; i++) {
cards.add(_buildCard(context, i));
}
cards.add(SizedBox.expand(
child: GestureDetector(
onPanUpdate: (final details) {
setState(() {
if (widget._allowVerticalMovement == true) {
frontCardAlign = Alignment(
frontCardAlign.x +
details.delta.dx * 20 / MediaQuery.of(context).size.width,
frontCardAlign.y +
details.delta.dy * 30 / MediaQuery.of(context).size.height,
);
} else {
frontCardAlign = Alignment(
frontCardAlign.x +
details.delta.dx * 20 / MediaQuery.of(context).size.width,
0,
);
if (widget.swipeUpdateCallback != null) {
widget.swipeUpdateCallback!(details, frontCardAlign);
}
}
if (widget.swipeUpdateCallback != null) {
widget.swipeUpdateCallback!(details, frontCardAlign);
}
});
},
onPanEnd: (final details) {
animateCards(TriggerDirection.none);
},
),
));
return cards;
}
void animateCards(TriggerDirection trigger) {
if (_animationController.isAnimating ||
_currentFront + widget._stackNum == 0) {
return;
}
_trigger = trigger;
_animationController.stop();
_animationController.value = 0.0;
_animationController.forward();
}
void triggerSwap(TriggerDirection trigger) {
animateCards(trigger);
}
// support for asynchronous data events
@override
void didUpdateWidget(covariant TinderSwapCard oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget._totalNum != oldWidget._totalNum) {
_initState();
}
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
_initState();
}
void _initState() {
_currentFront = widget._totalNum - widget._stackNum;
frontCardAlign = widget._cardAligns[widget._cardAligns.length - 1];
_animationController = AnimationController(
vsync: this,
duration: Duration(
milliseconds: widget._animDuration,
),
);
_animationController.addListener(() => setState(() {}));
_animationController.addStatusListener(
(final status) {
final index = widget._totalNum - widget._stackNum - _currentFront;
if (status == AnimationStatus.completed) {
CardSwipeOrientation orientation;
if (frontCardAlign.x < -widget._swipeEdge) {
orientation = CardSwipeOrientation.left;
} else if (frontCardAlign.x > widget._swipeEdge) {
orientation = CardSwipeOrientation.right;
} else if (frontCardAlign.y < -widget._swipeEdgeVertical) {
orientation = CardSwipeOrientation.up;
} else if (frontCardAlign.y > widget._swipeEdgeVertical) {
orientation = CardSwipeOrientation.down;
} else {
frontCardAlign = widget._cardAligns[widget._stackNum - 1];
orientation = CardSwipeOrientation.recover;
}
if (widget.swipeCompleteCallback != null) {
widget.swipeCompleteCallback!(orientation, index);
}
if (orientation != CardSwipeOrientation.recover) changeCardOrder();
}
},
);
}
@override
Widget build(BuildContext context) {
widget.cardController?.addListener(triggerSwap);
return Stack(children: _buildCards(context));
}
void changeCardOrder() {
setState(() {
_currentFront--;
frontCardAlign = widget._cardAligns[widget._stackNum - 1];
});
}
}
typedef CardBuilder = Widget Function(BuildContext context, int index);
enum CardSwipeOrientation { left, right, recover, up, down }
/// swipe card to [CardSwipeOrientation.left] or [CardSwipeOrientation.right]
/// , [CardSwipeOrientation.recover] means back to start.
typedef CardSwipeCompleteCallback = void Function(
CardSwipeOrientation orientation, int index);
/// [DragUpdateDetails] of swiping card.
typedef CardDragUpdateCallback = void Function(
DragUpdateDetails details, Alignment align);
enum AmassOrientation { top, bottom, left, right }
class CardAnimation {
static Animation<Alignment> frontCardAlign(
AnimationController controller,
Alignment beginAlign,
Alignment baseAlign,
double swipeEdge,
bool swipeUp,
bool swipeDown,
) {
double endX, endY;
if (_TinderSwapCardState._trigger == TriggerDirection.none) {
endX = beginAlign.x > 0
? (beginAlign.x > swipeEdge ? beginAlign.x + 10.0 : baseAlign.x)
: (beginAlign.x < -swipeEdge ? beginAlign.x - 10.0 : baseAlign.x);
endY = beginAlign.x > 3.0 || beginAlign.x < -swipeEdge
? beginAlign.y
: baseAlign.y;
if (swipeUp || swipeDown) {
if (beginAlign.y < 0) {
if (swipeUp) {
endY =
beginAlign.y < -swipeEdge ? beginAlign.y - 10.0 : baseAlign.y;
}
} else if (beginAlign.y > 0) {
if (swipeDown) {
endY = beginAlign.y > swipeEdge ? beginAlign.y + 10.0 : baseAlign.y;
}
}
}
} else if (_TinderSwapCardState._trigger == TriggerDirection.left) {
endX = beginAlign.x - swipeEdge;
endY = beginAlign.y + 0.5;
}
/* Trigger Swipe Up or Down */
else if (_TinderSwapCardState._trigger == TriggerDirection.up ||
_TinderSwapCardState._trigger == TriggerDirection.down) {
var beginY =
_TinderSwapCardState._trigger == TriggerDirection.up ? -10 : 10;
endY = beginY < -swipeEdge ? beginY - 10.0 : baseAlign.y;
endX = beginAlign.x > 0
? (beginAlign.x > swipeEdge ? beginAlign.x + 10.0 : baseAlign.x)
: (beginAlign.x < -swipeEdge ? beginAlign.x - 10.0 : baseAlign.x);
} else {
endX = beginAlign.x + swipeEdge;
endY = beginAlign.y + 0.5;
}
return AlignmentTween(
begin: beginAlign,
end: Alignment(endX, endY),
).animate(
CurvedAnimation(
parent: controller,
curve: Curves.easeOut,
),
);
}
static Animation<double> frontCardRota(
AnimationController controller, double beginRot) {
return Tween(begin: beginRot, end: 0.0).animate(
CurvedAnimation(
parent: controller,
curve: Curves.easeOut,
),
);
}
static Animation<Size?> backCardSize(
AnimationController controller,
Size beginSize,
Size endSize,
) {
return SizeTween(begin: beginSize, end: endSize).animate(
CurvedAnimation(
parent: controller,
curve: Curves.easeOut,
),
);
}
static Animation<Alignment> backCardAlign(
AnimationController controller,
Alignment beginAlign,
Alignment endAlign,
) {
return AlignmentTween(begin: beginAlign, end: endAlign).animate(
CurvedAnimation(
parent: controller,
curve: Curves.easeOut,
),
);
}
}
typedef TriggerListener = void Function(TriggerDirection trigger);
class CardController {
late TriggerListener? _listener;
void triggerLeft() {
if (_listener != null) {
_listener!(TriggerDirection.left);
}
}
void triggerRight() {
if (_listener != null) {
_listener!(TriggerDirection.right);
}
}
void triggerUp() {
if (_listener != null) {
_listener!(TriggerDirection.up);
}
}
void triggerDown() {
if (_listener != null) {
_listener!(TriggerDirection.down);
}
}
// ignore: use_setters_to_change_properties
void addListener(final TriggerListener listener) {
_listener = listener;
}
void removeListener() {
_listener = null;
}
}
Upvotes: 1
Views: 451
Reputation: 2792
i pass in the current
index to swipeUpdateCallback
then set SwipeUp to false
...
here is the full sample code
import 'dart:async';
import 'dart:math';
import 'package:card/card.dart';
import 'package:card/up.dart';
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
late StreamController<List<String>> _streamController;
class _HomePageState extends State<HomePage> {
List<String> welcomeImages = [
"assets/welcome0.png",
"assets/welcome1.png",
"assets/welcome2.png",
];
@override
initState() {
_streamController = StreamController<List<String>>();
super.initState();
}
void _addToStream() {
Random random = Random();
int index = random.nextInt(3);
welcomeImages.add('assets/welcome$index.png');
_streamController.add(welcomeImages);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("asynchronous data events demo"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Added image appears on top:',
),
StreamBuilder<List<String>>(
stream: _streamController.stream,
initialData: welcomeImages,
builder:
(BuildContext context, AsyncSnapshot<List<String>> snapshot) {
print('snapshot.data.length: ${snapshot.data!.length}');
if (snapshot.hasError) return Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Add image');
case ConnectionState.waiting:
case ConnectionState.active:
return _asyncDataExample(
context,
snapshot.data!,
(CardSwipeOrientation orientation) {
// welcomeImages[0] is the swiped card
// you can send to backend service in here
welcomeImages.removeAt(0);
_streamController.add(welcomeImages);
},
);
case ConnectionState.done:
return Text('\$${snapshot.data} (closed)');
}
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _addToStream,
tooltip: 'Add image',
child: Icon(Icons.add),
),
);
}
Widget _asyncDataExample(
BuildContext context, List<String> imageList, Function onSwipe) {
CardController controller; //Use this to trigger swap.
return Center(
child: Container(
height: MediaQuery.of(context).size.height * 0.6,
child: TinderSwapCard(
orientation: AmassOrientation.bottom,
totalNum: imageList.length,
stackNum: 4,
swipeEdge: 4.0,
maxWidth: MediaQuery.of(context).size.width * 0.9,
maxHeight: MediaQuery.of(context).size.width * 0.9,
minWidth: MediaQuery.of(context).size.width * 0.8,
minHeight: MediaQuery.of(context).size.width * 0.8,
cardBuilder: (context, index) => Card(
child: Image.asset('${imageList[index]}'),
),
cardController: controller = CardController(),
swipeUpdateCallback:
(DragUpdateDetails details, Alignment align, int index) {
/// Get swiping card's alignment
if (align.y < -10) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => SwipeUp()));
}
},
swipeCompleteCallback: (CardSwipeOrientation orientation, int index) {
if (orientation != CardSwipeOrientation.recover) {
onSwipe(orientation);
}
if (orientation == CardSwipeOrientation.up) {}
},
),
),
);
}
}
Upvotes: 1