Comments (3)
If you wanted to leave it as default, just make a few changes:
If you don't want the animation to drag the widget to the cart, null safety is in both methods
createAddToCartAnimation
If you want the animation to be according to the quantity that will be added to the cart
createAnimationByQty
class AddToCartAnimation
final Function(Future<void> Function(GlobalKey))? createAddToCartAnimation;
/// It's the same principle as [createAddToCartAnimation] the only difference
/// is that the animation will be multiplied according to the amount passed.
final Function(Future<void> Function(GlobalKey, int))? createAnimationByQty;
null safety check
@override
void initState() {
if (this.widget.createAddToCartAnimation != null) {
this.widget.createAddToCartAnimation!(runAddToCartAnimation);
}
if (this.widget.createAnimationByQty != null) {
this.widget.createAnimationByQty!(animationByQty);
}
super.initState();
}
// Method to make animation according to quantity
Future<void> animationByQty(GlobalKey widgetKey, int qty) async {
for (var i = 0; i < qty; i++) {
runAddToCartAnimation(widgetKey);
await Future.delayed(const Duration(milliseconds: 200));
}
}
end of changes in class addToCartAnimation
Call
// Start the variable in the controller or class MyHomePageState extends State<MyHomePage>
late Function(GlobalKey, int) animationByQty;
// @override
// Widget build(BuildContext context)
return AddToCartAnimation(
// To send the library the location of the Cart icon
cartKey: controller.cartKey,
height: 30,
width: 30,
opacity: 0.85,
dragAnimation: const DragToCartAnimationOptions(rotation: true),
jumpAnimation: const JumpAnimationOptions(),
createAnimationByQty: (animationByQty) {
controller.animationByQty = animationByQty;
},
Method that does the magic, can be in the controller or on the same page
Future<void> listClick(GlobalKey widgetKey, int quant) async {
await animationByQty(widgetKey, quant);
cartTotalItems += quant;
await cartKey.currentState!.runCartAnimation((cartTotalItems).toString());
}
Full code StatefulWidget
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
MyHomePageState createState() => MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
// We can detect the location of the cart by this GlobalKey<CartIconKey>
GlobalKey<CartIconKey> cartKey = GlobalKey<CartIconKey>();
// late Function(GlobalKey) runAddToCartAnimation;
late Function(GlobalKey, int) animationByQty;
var _cartQuantityItems = 0;
@override
Widget build(BuildContext context) {
return AddToCartAnimation(
// To send the library the location of the Cart icon
cartKey: cartKey,
height: 30,
width: 30,
opacity: 0.85,
dragAnimation: const DragToCartAnimationOptions(
rotation: true,
),
jumpAnimation: const JumpAnimationOptions(),
createAnimationByQty: (animationByQty) {
animationByQty = animationByQty;
},
/* createAddToCartAnimation: (runAddToCartAnimation) {
// You can run the animation by addToCartAnimationMethod, just pass trough the the global key of the image as parameter
this.runAddToCartAnimation = runAddToCartAnimation;
}, */
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: false,
actions: [
// Adding 'clear-cart-button'
IconButton(
icon: const Icon(Icons.cleaning_services),
onPressed: () {
_cartQuantityItems = 0;
cartKey.currentState!.runClearCartAnimation();
},
),
const SizedBox(width: 16),
AddToCartIcon(
key: cartKey,
icon: const Icon(Icons.shopping_cart),
badgeOptions: const BadgeOptions(
active: true,
backgroundColor: Colors.red,
),
),
const SizedBox(
width: 16,
)
],
),
body: ListView(
children: List.generate(
15,
(index) => AppListItem(
onClick: listClick,
index: index,
),
),
),
),
);
}
Future<void> listClick(GlobalKey widgetKey, int quant) async {
await animationByQty(widgetKey, quant);
_cartQuantityItems += quant;
await cartKey.currentState!
.runCartAnimation((_cartQuantityItems).toString());
}
/*
void listClick(GlobalKey widgetKey) async {
await runAddToCartAnimation(widgetKey);
await cartKey.currentState!
.runCartAnimation((++_cartQuantityItems).toString());
}
*/
}
Full code Class AddToCartAnimation
import 'dart:math';
import 'drag_to_cart_animation_options.dart';
import 'jump_animation_options.dart';
import 'add_to_cart_icon.dart';
import 'globalkeyext.dart';
import 'package:flutter/material.dart';
export 'add_to_cart_icon.dart';
export 'jump_animation_options.dart';
export 'drag_to_cart_animation_options.dart';
class _PositionedAnimationModel {
bool showAnimation = false;
bool animationActive = false;
Offset imageSourcePoint = Offset.zero;
Offset imageDestPoint = Offset.zero;
Size imageSourceSize = Size.zero;
Size imageDestSize = Size.zero;
bool rotation = false;
double opacity = 0.85;
late Container container;
Duration duration = Duration.zero;
Curve curve = Curves.easeIn;
}
/// An add to cart animation which provide you an animation by sliding the product to cart in the Flutter app
class AddToCartAnimation extends StatefulWidget {
final Widget child;
/// The Global Key of the [AddToCartIcon] element. We need it because we need to know where is the cart icon is located in the screen. Based on the location, we are dragging given widget to the cart.
final GlobalKey<CartIconKey> cartKey;
/// you can receive [runAddToCartAnimation] animation method on [createAddToCartAnimation].
/// [runAddToCartAnimation] animation method runs the add to cart animation based on the given parameters.
/// Add to cart animation drags the given widget to the cart based on their location via global keys
final Function(Future<void> Function(GlobalKey))? createAddToCartAnimation;
/// It's the same principle as [createAddToCartAnimation] the only difference
/// is that the animation will be multiplied according to the amount passed.
final Function(Future<void> Function(GlobalKey, int))? createAnimationByQty;
/// What Should the given widget's height while dragging to the cart
final double height;
/// What Should the given widget's width while dragging to the cart
final double width;
/// What Should the given widget's opacity while dragging to the cart
final double opacity;
/// Should the given widget jump before the dragging
final JumpAnimationOptions jumpAnimation;
/// The animation options while given widget sliding to cart
final DragToCartAnimationOptions dragAnimation;
const AddToCartAnimation({
Key? key,
required this.child,
required this.cartKey,
this.createAddToCartAnimation,
this.createAnimationByQty,
this.height = 30,
this.width = 30,
this.opacity = 0.85,
this.jumpAnimation = const JumpAnimationOptions(),
this.dragAnimation = const DragToCartAnimationOptions(),
}) : super(key: key);
@override
_AddToCartAnimationState createState() => _AddToCartAnimationState();
}
class _AddToCartAnimationState extends State<AddToCartAnimation> {
List<_PositionedAnimationModel> animationModels = [];
@override
void initState() {
if (this.widget.createAddToCartAnimation != null) {
this.widget.createAddToCartAnimation!(runAddToCartAnimation);
}
if (this.widget.createAnimationByQty != null) {
this.widget.createAnimationByQty!(animationByQty);
}
super.initState();
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
widget.child,
Positioned.fill(
child: Stack(
children: animationModels
.map<Widget>((model) => model.showAnimation
? AnimatedPositioned(
top: model.animationActive
? model.imageDestPoint.dx
: model.imageSourcePoint.dx,
left: model.animationActive
? model.imageDestPoint.dy
: model.imageSourcePoint.dy,
height: model.animationActive
? model.imageDestSize.height
: model.imageSourceSize.height,
width: model.animationActive
? model.imageDestSize.width
: model.imageSourceSize.width,
duration: model.duration,
curve: model.curve,
child: model.rotation
? TweenAnimationBuilder(
tween: Tween<double>(begin: 0, end: pi * 2),
duration: model.duration,
child: model.container,
builder: (context, double value, widget) {
return Transform.rotate(
angle: value,
child: Opacity(
opacity: model.opacity,
child: widget,
),
);
},
)
: Opacity(
opacity: model.opacity,
child: model.container,
),
)
: Container())
.toList(),
),
),
],
);
}
Future<void> animationByQty(GlobalKey widgetKey, int qty) async {
for (var i = 0; i < qty; i++) {
runAddToCartAnimation(widgetKey);
await Future.delayed(const Duration(milliseconds: 200));
}
}
Future<void> runAddToCartAnimation(GlobalKey widgetKey) async {
_PositionedAnimationModel animationModel = _PositionedAnimationModel()
..rotation = false
..opacity = widget.opacity;
animationModel.imageSourcePoint = Offset(
widgetKey.globalPaintBounds!.top, widgetKey.globalPaintBounds!.left);
// Improvement/Suggestion 1: Provinding option, in order to, use/or not initial "jumping" on image
var startingHeight = widget.jumpAnimation.active
? widgetKey.currentContext!.size!.height
: 0;
animationModel.imageDestPoint = Offset(
widgetKey.globalPaintBounds!.top - (startingHeight + widget.height),
widgetKey.globalPaintBounds!.left);
animationModel.imageSourceSize = Size(widgetKey.currentContext!.size!.width,
widgetKey.currentContext!.size!.height);
animationModel.imageDestSize = Size(
widgetKey.currentContext!.size!.width + widget.width,
widgetKey.currentContext!.size!.height + widget.height);
animationModels.add(animationModel);
// Improvement/Suggestion 2: Changing the animationModel.child from Image to gkImageContainer
animationModel.container = Container(
child: (widgetKey.currentWidget! as Container).child,
);
animationModel.showAnimation = true;
setState(() {});
await Future.delayed(Duration(milliseconds: 75));
animationModel.curve = widget.jumpAnimation.curve;
animationModel.duration =
widget.jumpAnimation.duration; // This is for preview mode
animationModel.animationActive = true; // That's start the animation.
setState(() {});
await Future.delayed(animationModel.duration);
// Drag to cart animation
animationModel.curve = widget.dragAnimation.curve;
animationModel.rotation = widget.dragAnimation.rotation;
animationModel.duration =
widget.dragAnimation.duration; // this is for add to button mode
animationModel.imageDestPoint = Offset(
this.widget.cartKey.globalPaintBounds!.top,
this.widget.cartKey.globalPaintBounds!.left);
animationModel.imageDestSize = Size(
this.widget.cartKey.currentContext!.size!.width,
this.widget.cartKey.currentContext!.size!.height);
setState(() {});
await Future.delayed(animationModel.duration);
animationModel.showAnimation = false;
animationModel.animationActive = false;
setState(() {});
// Improvement/Suggestion 4.3: runCartAnimation is running independently, using gkCart.currentState(main.dart)
// await this.widget.gkCart.currentState!.runCartAnimation();
return;
}
}
from add_to_cart_animation.
I temporarily solved it like this
Future<void> listClick(GlobalKey widgetKey, int quant) async {
for (var i = 0; i < quant; i++) {
runAddToCartAnimation(widgetKey);
await Future.delayed(const Duration(milliseconds: 200));
}
cartTotalItems += quant;
await cartKey.currentState!.runCartAnimation((cartTotalItems).toString());
}
from add_to_cart_animation.
It seems you already solved the issue. I am closing the issue. Thank you.
from add_to_cart_animation.
Related Issues (7)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from add_to_cart_animation.