How do I make a AnimatedController that repeats, but starts up with a curve animation.
AnimationController :
var _animating = false;
AnimationController _rotationAnimationController;
Animation<double> _animation;
@override
void initState() {
super.initState();
_rotationAnimationController = AnimationController(
duration: Duration(milliseconds: 2000),
vsync: this,
);
_animation =
Tween<double>(begin: 0, end: 4 * pi ).animate(_rotationAnimationController)
..addListener(() {
setState(() {});
});
}
@override
void dispose() {
_rotationAnimationController.dispose();
super.dispose();
}
Button :
GestureDetector(
onTap: () {
Duration startStopTime = Duration(seconds: 3);
if(_animating) {
_rotationAnimationController.animateBack(1, duration: startStopTime, curve: Curves.easeOut);
setState(() {});
} else {
_rotationAnimationController.repeat() //This needs to start with a curve
}
setState(() {
_animating = !_animating;
});
},
child: [...]
),
If you could also make it so that when the repeat stops, it does that with a curve, that would be amazing too :)
Thanks for the help allready :D
The best I understood your question , you want a CurvedAnimation
right ? This means your animation will repeat but follow a specific curve . So here the best I could do for you :
Define your AnimationController
like this :
Animation<double> _animation;
AnimationController _animationController;
@override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: Duration(seconds: 2))
..addListener(() {
setState(() {});
});
final Animation curve =
CurvedAnimation(parent: _animationController, curve: Curves.easeOut);
_animation = Tween<double>(begin: 0, end: pi * 4).animate(curve);
}
and your GestureDetector
like this :
GestureDetector(
onTap: () {
if (_animationController.isAnimating)
{
_animationController.animateBack(0,duration: Duration(seconds: 2), curve: Curves.easeIn);
}
else {
_animationController.repeat();
}
},
child: [...]
),
Edit :
I used a TweenAnimationBuilder
to have the effect you want :
import 'package:flutter/material.dart';
import 'dart:math' as math;
class TweenAnimatedBuilderRotate extends StatefulWidget {
TweenAnimatedBuilderRotate({Key key}) : super(key: key);
@override
TweenAnimatedBuilderRotateState createState() =>
TweenAnimatedBuilderRotateState();
}
class TweenAnimatedBuilderRotateState
extends State<TweenAnimatedBuilderRotate> {
double _newAngle = 0;
Curve curveThatChanges = Curves.easeIn;
bool isAnimating = false;
int _millsecs = 2000;
void onCompletion() {
if (isAnimating) {
_newAngle += 4 * math.pi;
curveThatChanges = Curves.linear;
_millsecs = 1000;
setState(() {});
} else {
_newAngle = 0;
_millsecs = 2000;
}
}
void onContainerTap() {
if (isAnimating) {
isAnimating = false;
_newAngle = _newAngle;
setState(() {});
} else {
curveThatChanges = Curves.easeIn;
_newAngle += 4 * math.pi;
isAnimating = true;
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return TweenAnimationBuilder(
tween: Tween<double>(begin: 0, end: _newAngle),
duration: Duration(milliseconds: _millsecs),
onEnd: () => onCompletion(),
curve: curveThatChanges,
builder: (
BuildContext ctx,
double angle,
Widget child,
) {
_newAngle = angle;
return Center(
child: Transform(
transform: Matrix4.identity()..rotateZ(_newAngle),
alignment: FractionalOffset.center,
child: GestureDetector(
child: Container(
color: Colors.blueGrey,
width: 200,
height: 200,
),
onTap: () => onContainerTap(),
),
),
);
});
}
}
You can refer to this Medium article to understand about how TweenAnimationdBuilder
Works. You can also modify _millsecs
variable to speed up/down the animation. Pass TweenAnimatedBuilderRotate()
in the body
parameter of the Scaffold(...)
.