hi guys I just started learning flutter animation and using flutter curves from flutter curve website using tween value which goes like
_animation = Tween<double>(begin: -100, end: 0).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.bounceInOut,
),
);)
i want to animate this in stack with the circular container with positioned widget using Animated builder code is likke this
Stack(
children: [
// background image view
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('images/sky.webp'), fit: BoxFit.cover),
),
),
//! I want to animate this like a bouncing ball
AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Positioned(
// This is the animation value as position of the circular container
bottom: _animation.value,
left: _animation.value + 50,
child: Container(
height: 250,
width: 250,
decoration: const BoxDecoration(
shape: BoxShape.circle,
// borderRadius: BorderRadius.only(
// topLeft: Radius.circular(15),
// topRight: Radius.circular(15),
// ),
image: DecorationImage(
image: AssetImage(
'images/colz.jpg',
),
fit: BoxFit.cover,
),
),
),
);
},
)
],
),
I want bounce direction as
from here start curve for bounceinout
--^
^---- > here the curve ends
this what happenens after the code
I think you may be better served by having two different animations that share the same controller to drive them. The controller to adjust the horizontal direction could be a different curve than the one that adjusts the horizontal direction.
I've modified your original code to do this, as well as added an example for how you might go about making your own curve that could give you that springiness that you want. Note that the demo curves I have at the bottom are very rough and can be janky if not paired up with linear primary curves. You could make them smoother by possibly averaging the starting and ending points of each curve - I will leave that up to you to modify.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _horizontalAnimation;
late Animation<double> _verticalAnimation;
@override
void initState() {
_controller = AnimationController(
vsync: this,
duration: const Duration(
seconds: 5,
),
);
_horizontalAnimation = Tween<double>(begin: -1.0, end: 1.0).animate(
CurvedAnimation(
parent: _controller,
// curve: Curves.bounceInOut,
// TODO: Try to experiment with this a bit too!
curve: const InterpolateCurve(
primary: Curves.linear,
secondary: Curves.bounceInOut,
),
),
);
_verticalAnimation = Tween<double>(begin: -1.0, end: 1.0).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.linear,
// TODO: You may even be able to experiment with this a bit
// curve: const InterpolateCurve(
// primary: Curves.linear,
// secondary: WhipCurve(Curves.easeInOut),
// startTransition: 0.2,
// endTransition: 0.8,
// ),
),
);
super.initState();
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Drag and Drop Example'),
),
body: Stack(
children: [
// background image view
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: NetworkImage(
'https://hdwallpaperim.com/wp-content/uploads/2017/08/25/462707-universe-galaxy-space-stars.jpg'),
fit: BoxFit.cover),
),
),
//! I want to animate this like a bouncing ball
AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Align(
alignment: Alignment(
_horizontalAnimation.value, _verticalAnimation.value),
// This is the animation value as position of the circular container
child: Container(
height: 250,
width: 250,
decoration: BoxDecoration(
shape: BoxShape.circle,
// borderRadius: BorderRadius.only(
// topLeft: Radius.circular(15),
// topRight: Radius.circular(15),
// ),
// image: DecorationImage(
// image: AssetImage(
// 'images/colz.jpg',
// ),
// fit: BoxFit.cover,
// ),
color: Colors.indigo.shade900,
),
),
);
},
)
],
),
);
}
}
// Try this too:
class InterpolateCurve extends Curve {
final Curve primary;
final Curve secondary;
final double startTransition;
final double endTransition;
const InterpolateCurve({
required this.primary,
required this.secondary,
this.startTransition = 0.4,
this.endTransition = 0.6,
});
@override
double transform(double t) {
t = t.clamp(0.0, 1.0);
// We want to squiggle in the middle a bit so...
if (t <= startTransition || t >= endTransition) {
return primary.transform(t);
}
final double centerPeriod = endTransition - startTransition;
final double centerSegementScalar = 1.0 / centerPeriod;
t = (t - startTransition) * centerSegementScalar;
t = t.clamp(0.0, 1.0);
t = secondary.transform(t);
t = (t / centerSegementScalar) + startTransition;
return t;
}
}
class WhipCurve extends Curve {
final Curve curve;
const WhipCurve(
this.curve,
);
@override
double transform(double t) {
t = t.clamp(0.0, 1.0);
if (t <= 1 / 3) {
return curve.transform(t * 3);
}
if (t >= 2 / 3) {
t = t - (2 / 3);
return curve.transform(t * 3);
} else {
t = (t - (1 / 3));
return 1.0 - curve.transform(t * 3);
}
}
}
Also note that I swapped your Positioned widget for an Align widget; I think Align may be what you want- Positioned in order to get it to move across the screen would require some MediaQuery.of(context).size calls to properly scale it to the screen, whereas Align will just keep it on the screen.
And I obviously didn't have your images, so you'd need to add those back.