What would be the proper way to update animation values in a Flutter animation?











up vote
0
down vote

favorite












So I'm trying to create an animation in Flutter that requires a different outcome every time the user presses a button.



I've implemented the following code according to the Flutter Animations tutorial and created a function to update it.



class _RoulettePageWidgetState extends State<RoulettePageWidget>
with SingleTickerProviderStateMixin {
Animation<double> _animation;
Tween<double> _tween;
AnimationController _animationController;

int position = 0;

@override
void initState() {
super.initState();
_animationController =
AnimationController(duration: Duration(seconds: 2), vsync: this);
_tween = Tween(begin: 0.0, end: 100.0);
_animation = _tween.animate(_animationController)
..addListener(() {
setState(() {});
});
}

void setNewPosition(int newPosition) {
_tween = Tween(
begin: 0.0,
end: math.pi*2/25*newPosition);
_animationController.reset();
_tween.animate(_animationController);
_animationController.forward();
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Center(
child: Transform.rotate(
angle: _animationController.value,
child: Icon(
Icons.arrow_upward,
size: 250.0,
),
)),
Expanded(
child: Container(),
),
RaisedButton(
child: Text('SPIN'),
onPressed: () {
setState(() {
setNewPosition(math.Random().nextInt(25));
});
},
)
],
)
);
}
}


As you can see I'm updating the _tween's begin: and end: but this doesn't seem to change the animation.



So what should I be doing to create a 'different' animation every time the users presses the button?



The general idea is to make the animations build upon each other with a random new value so for example:




  • first spin: 0 -> 10

  • second spin: 10 -> 13

  • third spin: 13 -> 18

  • ... etc


So I wondered if I could update the animation, or should I create a new animation every time?
Another thing I could think of was tracking the positions and use the same animation every time (0.0 -> 100.0) to act as a percentage of the transfer.



So instead of creating a new animation from 10 -> 15 I would be doing something like:
currentValue = 10 + (15-10)/100*_animationController.value










share|improve this question
























  • could you also share your setNewPosition call?
    – salihguler
    Nov 10 at 20:32










  • I mean your build method would be really useful because right now, I feel what you are asking as a bit abstract.
    – salihguler
    Nov 10 at 20:36










  • I've added the build implementation.
    – SEG.Veenstra
    Nov 10 at 20:47










  • It does reset the animation and it's also playing again but with the initial values and not the new once.
    – SEG.Veenstra
    Nov 10 at 20:48















up vote
0
down vote

favorite












So I'm trying to create an animation in Flutter that requires a different outcome every time the user presses a button.



I've implemented the following code according to the Flutter Animations tutorial and created a function to update it.



class _RoulettePageWidgetState extends State<RoulettePageWidget>
with SingleTickerProviderStateMixin {
Animation<double> _animation;
Tween<double> _tween;
AnimationController _animationController;

int position = 0;

@override
void initState() {
super.initState();
_animationController =
AnimationController(duration: Duration(seconds: 2), vsync: this);
_tween = Tween(begin: 0.0, end: 100.0);
_animation = _tween.animate(_animationController)
..addListener(() {
setState(() {});
});
}

void setNewPosition(int newPosition) {
_tween = Tween(
begin: 0.0,
end: math.pi*2/25*newPosition);
_animationController.reset();
_tween.animate(_animationController);
_animationController.forward();
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Center(
child: Transform.rotate(
angle: _animationController.value,
child: Icon(
Icons.arrow_upward,
size: 250.0,
),
)),
Expanded(
child: Container(),
),
RaisedButton(
child: Text('SPIN'),
onPressed: () {
setState(() {
setNewPosition(math.Random().nextInt(25));
});
},
)
],
)
);
}
}


As you can see I'm updating the _tween's begin: and end: but this doesn't seem to change the animation.



So what should I be doing to create a 'different' animation every time the users presses the button?



The general idea is to make the animations build upon each other with a random new value so for example:




  • first spin: 0 -> 10

  • second spin: 10 -> 13

  • third spin: 13 -> 18

  • ... etc


So I wondered if I could update the animation, or should I create a new animation every time?
Another thing I could think of was tracking the positions and use the same animation every time (0.0 -> 100.0) to act as a percentage of the transfer.



So instead of creating a new animation from 10 -> 15 I would be doing something like:
currentValue = 10 + (15-10)/100*_animationController.value










share|improve this question
























  • could you also share your setNewPosition call?
    – salihguler
    Nov 10 at 20:32










  • I mean your build method would be really useful because right now, I feel what you are asking as a bit abstract.
    – salihguler
    Nov 10 at 20:36










  • I've added the build implementation.
    – SEG.Veenstra
    Nov 10 at 20:47










  • It does reset the animation and it's also playing again but with the initial values and not the new once.
    – SEG.Veenstra
    Nov 10 at 20:48













up vote
0
down vote

favorite









up vote
0
down vote

favorite











So I'm trying to create an animation in Flutter that requires a different outcome every time the user presses a button.



I've implemented the following code according to the Flutter Animations tutorial and created a function to update it.



class _RoulettePageWidgetState extends State<RoulettePageWidget>
with SingleTickerProviderStateMixin {
Animation<double> _animation;
Tween<double> _tween;
AnimationController _animationController;

int position = 0;

@override
void initState() {
super.initState();
_animationController =
AnimationController(duration: Duration(seconds: 2), vsync: this);
_tween = Tween(begin: 0.0, end: 100.0);
_animation = _tween.animate(_animationController)
..addListener(() {
setState(() {});
});
}

void setNewPosition(int newPosition) {
_tween = Tween(
begin: 0.0,
end: math.pi*2/25*newPosition);
_animationController.reset();
_tween.animate(_animationController);
_animationController.forward();
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Center(
child: Transform.rotate(
angle: _animationController.value,
child: Icon(
Icons.arrow_upward,
size: 250.0,
),
)),
Expanded(
child: Container(),
),
RaisedButton(
child: Text('SPIN'),
onPressed: () {
setState(() {
setNewPosition(math.Random().nextInt(25));
});
},
)
],
)
);
}
}


As you can see I'm updating the _tween's begin: and end: but this doesn't seem to change the animation.



So what should I be doing to create a 'different' animation every time the users presses the button?



The general idea is to make the animations build upon each other with a random new value so for example:




  • first spin: 0 -> 10

  • second spin: 10 -> 13

  • third spin: 13 -> 18

  • ... etc


So I wondered if I could update the animation, or should I create a new animation every time?
Another thing I could think of was tracking the positions and use the same animation every time (0.0 -> 100.0) to act as a percentage of the transfer.



So instead of creating a new animation from 10 -> 15 I would be doing something like:
currentValue = 10 + (15-10)/100*_animationController.value










share|improve this question















So I'm trying to create an animation in Flutter that requires a different outcome every time the user presses a button.



I've implemented the following code according to the Flutter Animations tutorial and created a function to update it.



class _RoulettePageWidgetState extends State<RoulettePageWidget>
with SingleTickerProviderStateMixin {
Animation<double> _animation;
Tween<double> _tween;
AnimationController _animationController;

int position = 0;

@override
void initState() {
super.initState();
_animationController =
AnimationController(duration: Duration(seconds: 2), vsync: this);
_tween = Tween(begin: 0.0, end: 100.0);
_animation = _tween.animate(_animationController)
..addListener(() {
setState(() {});
});
}

void setNewPosition(int newPosition) {
_tween = Tween(
begin: 0.0,
end: math.pi*2/25*newPosition);
_animationController.reset();
_tween.animate(_animationController);
_animationController.forward();
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Center(
child: Transform.rotate(
angle: _animationController.value,
child: Icon(
Icons.arrow_upward,
size: 250.0,
),
)),
Expanded(
child: Container(),
),
RaisedButton(
child: Text('SPIN'),
onPressed: () {
setState(() {
setNewPosition(math.Random().nextInt(25));
});
},
)
],
)
);
}
}


As you can see I'm updating the _tween's begin: and end: but this doesn't seem to change the animation.



So what should I be doing to create a 'different' animation every time the users presses the button?



The general idea is to make the animations build upon each other with a random new value so for example:




  • first spin: 0 -> 10

  • second spin: 10 -> 13

  • third spin: 13 -> 18

  • ... etc


So I wondered if I could update the animation, or should I create a new animation every time?
Another thing I could think of was tracking the positions and use the same animation every time (0.0 -> 100.0) to act as a percentage of the transfer.



So instead of creating a new animation from 10 -> 15 I would be doing something like:
currentValue = 10 + (15-10)/100*_animationController.value







animation dart flutter flutter-animation






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 10 at 20:46

























asked Nov 10 at 20:22









SEG.Veenstra

888




888












  • could you also share your setNewPosition call?
    – salihguler
    Nov 10 at 20:32










  • I mean your build method would be really useful because right now, I feel what you are asking as a bit abstract.
    – salihguler
    Nov 10 at 20:36










  • I've added the build implementation.
    – SEG.Veenstra
    Nov 10 at 20:47










  • It does reset the animation and it's also playing again but with the initial values and not the new once.
    – SEG.Veenstra
    Nov 10 at 20:48


















  • could you also share your setNewPosition call?
    – salihguler
    Nov 10 at 20:32










  • I mean your build method would be really useful because right now, I feel what you are asking as a bit abstract.
    – salihguler
    Nov 10 at 20:36










  • I've added the build implementation.
    – SEG.Veenstra
    Nov 10 at 20:47










  • It does reset the animation and it's also playing again but with the initial values and not the new once.
    – SEG.Veenstra
    Nov 10 at 20:48
















could you also share your setNewPosition call?
– salihguler
Nov 10 at 20:32




could you also share your setNewPosition call?
– salihguler
Nov 10 at 20:32












I mean your build method would be really useful because right now, I feel what you are asking as a bit abstract.
– salihguler
Nov 10 at 20:36




I mean your build method would be really useful because right now, I feel what you are asking as a bit abstract.
– salihguler
Nov 10 at 20:36












I've added the build implementation.
– SEG.Veenstra
Nov 10 at 20:47




I've added the build implementation.
– SEG.Veenstra
Nov 10 at 20:47












It does reset the animation and it's also playing again but with the initial values and not the new once.
– SEG.Veenstra
Nov 10 at 20:48




It does reset the animation and it's also playing again but with the initial values and not the new once.
– SEG.Veenstra
Nov 10 at 20:48












2 Answers
2






active

oldest

votes

















up vote
2
down vote



accepted










I'm going to skip your code a bit, and focus on what you're really asking:




The general idea is to make the animations build upon each other with a random new value so for example:




  • first spin: 0 -> 10


  • second spin: 10 -> 13


  • third spin: 13 -> 18


  • ... etc





With an explicit animation like this, there are three objects you are interested in:




  • a controller, which is a special kind of Animation that simply generates values linearly from its lower to its upper bound (both doubles, typically 0.0 and 1.0). You can control the flow of the animation - send it running forward, reverse it, stop it, or reset it.


  • a tween, which isn't an Animation but rather an Animatable. A tween defines the interpolation between two values, which don't even have to be numbers. It implements a transform method under the hood that takes in the current value of an animation and spits out the actual value you want to work with: another number, a color, a linear gradient, even a whole widget. This is what you should use to generate your angles of rotation.


  • an animation, which is the animation whose value you're actually going to work with (so this is where you'd grab values to build with). You get this by giving your tween a parent Animation to transform - this might be your controller directly but can also be some other sort of animation you've built on it (like a CurvedAnimation, which would give you easing or bouncy/elastic curves and so on). Flutter's animations are highly composable that way.



Your code is failing largely because you're not actually using the top-level animation you created in your build method and you're creating a new tween and animation every time you call setNewPosition. You can use the same tween and animation for multiple animation "cycles" - simply change the begin and end properties of the existing tween and it bubbles up to the animation. That ends up something like this:



class _RoulettePageWidgetState extends State<RoulettePageWidget>
with SingleTickerProviderStateMixin {
Animation<double> _animation;
Tween<double> _tween;
AnimationController _animationController;
math.Random _random = math.Random();

int position = 0;

double getRandomAngle() {
return math.pi * 2 / 25 * _random.nextInt(25);
}

@override
void initState() {
super.initState();
_animationController =
AnimationController(duration: Duration(seconds: 2), vsync: this);
_tween = Tween(begin: 0.0, end: getRandomAngle());
_animation = _tween.animate(_animationController)
..addListener(() {
setState(() {});
});
}

void setNewPosition() {
_tween.begin = _tween.end;
_animationController.reset();
_tween.end = getRandomAngle();
_animationController.forward();
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Center(
child: Transform.rotate(
angle: _animation.value,
child: Icon(
Icons.arrow_upward,
size: 250.0,
),
)),
Expanded(
child: Container(),
),
RaisedButton(
child: Text('SPIN'),
onPressed: setNewPosition,
)
],
)
);
}
}


Hope that helps!






share|improve this answer























  • Not only does this answer my question but your explanation really helps me to understand the whole concept. Funny thing is that I basically had this before I tried creating a new Tween except for reading out the right animation object!
    – SEG.Veenstra
    Nov 10 at 21:55






  • 1




    You're welcome! Also you should look into the AnimatedBuilder widget once you've got a good grasp of how Flutter handles animations :)
    – filleduchaos
    Nov 10 at 21:59










  • I will! I saw all kinds of interesting Widgets to experiment with.
    – SEG.Veenstra
    Nov 10 at 22:01


















up vote
0
down vote













While working, in no situation will you actually want to make these animations within your layout as explained by @filleduchaos.



This is under optimized, as you're rebuilding far more than you should for the animation. And it's a pain to write yourself.



You'll want to use the AnimatedWidget family for this. They are divided into two
kinds:




  • XXTransition

  • AnimatedXX


The first is a low layer that consumes an Animation and listens to it so that you don't need to do that ugly :



..addListener(() {
setState(() {});
});


The second handles the remaining pieces: AnimationController, TickerProvider and Tween.



This makes using animations much easier as it's almost entirely automatical.



In your case a rotation example would be as followed:



class RotationExample extends StatefulWidget {
final Widget child;

const RotationExample({
Key key,
this.child,
}) : super(key: key);

@override
RotationExampleState createState() {
return new RotationExampleState();
}
}

class RotationExampleState extends State<RotationExample> {
final _random = math.Random();
double rad = 0.0;

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _rotate,
child: AnimatedTransform(
duration: const Duration(seconds: 1),
alignment: Alignment.center,
transform: Matrix4.rotationZ(rad),
child: Container(
color: Colors.red,
height: 42.0,
width: 42.0,
),
),
);
}

void _rotate() {
setState(() {
rad = math.pi * 2 / 25 * _random.nextInt(25);
});
}
}


Easier right?



The irony is that Flutter forgot to provide an AnimatedTransform (even although we have many others !). But no worries, I made it for you!



The AnimatedTransform implementation is as followed :



class AnimatedTransform extends ImplicitlyAnimatedWidget {
final Matrix4 transform;
final AlignmentGeometry alignment;
final bool transformHitTests;
final Offset origin;
final Widget child;

const AnimatedTransform({
Key key,
@required this.transform,
@required Duration duration,
this.alignment,
this.transformHitTests = true,
this.origin,
this.child,
Curve curve = Curves.linear,
}) : assert(transform != null),
assert(duration != null),
super(
key: key,
duration: duration,
curve: curve,
);

@override
_AnimatedTransformState createState() => _AnimatedTransformState();
}

class _AnimatedTransformState
extends AnimatedWidgetBaseState<AnimatedTransform> {
Matrix4Tween _transform;

@override
void forEachTween(TweenVisitor<dynamic> visitor) {
_transform = visitor(_transform, widget.transform,
(dynamic value) => Matrix4Tween(begin: value));
}

@override
Widget build(BuildContext context) {
return Transform(
alignment: widget.alignment,
transform: _transform.evaluate(animation),
transformHitTests: widget.transformHitTests,
origin: widget.origin,
child: widget.child,
);
}
}


I will submit a pull request so that in the future you won't need this bit of code.






share|improve this answer























  • Eh, they're clearly working on understanding explicit animations. You don't always want widgets to implicitly animate themselves, and it's better to figure out how the Animation/Animatable stack works with something as easy as doubles.
    – filleduchaos
    Nov 11 at 0:11










  • But in production, this is what you'd want to use instead of the previous code. The fact that he's learning doesn't justify a partial answer.
    – Rémi Rousselet
    Nov 11 at 0:20










  • They're following an official tutorial that's explicitly about explicit animations and asked for help with that. I don't see how explaining why they're stuck on their tutorial about explicit animations is a partial answer.
    – filleduchaos
    Nov 11 at 0:29










  • There literally is the rest of the tutorial right there, which also touches on AnimatedWidget and AnimatedBuilder.
    – filleduchaos
    Nov 11 at 0:31










  • He's not following the tutorial, he's using it as a reference for his own project. But this doesn't matter anyway, the purpose of StackOverflow is to provide helpful answers for the whole world to see. If this helps, then it's fine.
    – Rémi Rousselet
    Nov 11 at 0:38











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53243077%2fwhat-would-be-the-proper-way-to-update-animation-values-in-a-flutter-animation%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
2
down vote



accepted










I'm going to skip your code a bit, and focus on what you're really asking:




The general idea is to make the animations build upon each other with a random new value so for example:




  • first spin: 0 -> 10


  • second spin: 10 -> 13


  • third spin: 13 -> 18


  • ... etc





With an explicit animation like this, there are three objects you are interested in:




  • a controller, which is a special kind of Animation that simply generates values linearly from its lower to its upper bound (both doubles, typically 0.0 and 1.0). You can control the flow of the animation - send it running forward, reverse it, stop it, or reset it.


  • a tween, which isn't an Animation but rather an Animatable. A tween defines the interpolation between two values, which don't even have to be numbers. It implements a transform method under the hood that takes in the current value of an animation and spits out the actual value you want to work with: another number, a color, a linear gradient, even a whole widget. This is what you should use to generate your angles of rotation.


  • an animation, which is the animation whose value you're actually going to work with (so this is where you'd grab values to build with). You get this by giving your tween a parent Animation to transform - this might be your controller directly but can also be some other sort of animation you've built on it (like a CurvedAnimation, which would give you easing or bouncy/elastic curves and so on). Flutter's animations are highly composable that way.



Your code is failing largely because you're not actually using the top-level animation you created in your build method and you're creating a new tween and animation every time you call setNewPosition. You can use the same tween and animation for multiple animation "cycles" - simply change the begin and end properties of the existing tween and it bubbles up to the animation. That ends up something like this:



class _RoulettePageWidgetState extends State<RoulettePageWidget>
with SingleTickerProviderStateMixin {
Animation<double> _animation;
Tween<double> _tween;
AnimationController _animationController;
math.Random _random = math.Random();

int position = 0;

double getRandomAngle() {
return math.pi * 2 / 25 * _random.nextInt(25);
}

@override
void initState() {
super.initState();
_animationController =
AnimationController(duration: Duration(seconds: 2), vsync: this);
_tween = Tween(begin: 0.0, end: getRandomAngle());
_animation = _tween.animate(_animationController)
..addListener(() {
setState(() {});
});
}

void setNewPosition() {
_tween.begin = _tween.end;
_animationController.reset();
_tween.end = getRandomAngle();
_animationController.forward();
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Center(
child: Transform.rotate(
angle: _animation.value,
child: Icon(
Icons.arrow_upward,
size: 250.0,
),
)),
Expanded(
child: Container(),
),
RaisedButton(
child: Text('SPIN'),
onPressed: setNewPosition,
)
],
)
);
}
}


Hope that helps!






share|improve this answer























  • Not only does this answer my question but your explanation really helps me to understand the whole concept. Funny thing is that I basically had this before I tried creating a new Tween except for reading out the right animation object!
    – SEG.Veenstra
    Nov 10 at 21:55






  • 1




    You're welcome! Also you should look into the AnimatedBuilder widget once you've got a good grasp of how Flutter handles animations :)
    – filleduchaos
    Nov 10 at 21:59










  • I will! I saw all kinds of interesting Widgets to experiment with.
    – SEG.Veenstra
    Nov 10 at 22:01















up vote
2
down vote



accepted










I'm going to skip your code a bit, and focus on what you're really asking:




The general idea is to make the animations build upon each other with a random new value so for example:




  • first spin: 0 -> 10


  • second spin: 10 -> 13


  • third spin: 13 -> 18


  • ... etc





With an explicit animation like this, there are three objects you are interested in:




  • a controller, which is a special kind of Animation that simply generates values linearly from its lower to its upper bound (both doubles, typically 0.0 and 1.0). You can control the flow of the animation - send it running forward, reverse it, stop it, or reset it.


  • a tween, which isn't an Animation but rather an Animatable. A tween defines the interpolation between two values, which don't even have to be numbers. It implements a transform method under the hood that takes in the current value of an animation and spits out the actual value you want to work with: another number, a color, a linear gradient, even a whole widget. This is what you should use to generate your angles of rotation.


  • an animation, which is the animation whose value you're actually going to work with (so this is where you'd grab values to build with). You get this by giving your tween a parent Animation to transform - this might be your controller directly but can also be some other sort of animation you've built on it (like a CurvedAnimation, which would give you easing or bouncy/elastic curves and so on). Flutter's animations are highly composable that way.



Your code is failing largely because you're not actually using the top-level animation you created in your build method and you're creating a new tween and animation every time you call setNewPosition. You can use the same tween and animation for multiple animation "cycles" - simply change the begin and end properties of the existing tween and it bubbles up to the animation. That ends up something like this:



class _RoulettePageWidgetState extends State<RoulettePageWidget>
with SingleTickerProviderStateMixin {
Animation<double> _animation;
Tween<double> _tween;
AnimationController _animationController;
math.Random _random = math.Random();

int position = 0;

double getRandomAngle() {
return math.pi * 2 / 25 * _random.nextInt(25);
}

@override
void initState() {
super.initState();
_animationController =
AnimationController(duration: Duration(seconds: 2), vsync: this);
_tween = Tween(begin: 0.0, end: getRandomAngle());
_animation = _tween.animate(_animationController)
..addListener(() {
setState(() {});
});
}

void setNewPosition() {
_tween.begin = _tween.end;
_animationController.reset();
_tween.end = getRandomAngle();
_animationController.forward();
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Center(
child: Transform.rotate(
angle: _animation.value,
child: Icon(
Icons.arrow_upward,
size: 250.0,
),
)),
Expanded(
child: Container(),
),
RaisedButton(
child: Text('SPIN'),
onPressed: setNewPosition,
)
],
)
);
}
}


Hope that helps!






share|improve this answer























  • Not only does this answer my question but your explanation really helps me to understand the whole concept. Funny thing is that I basically had this before I tried creating a new Tween except for reading out the right animation object!
    – SEG.Veenstra
    Nov 10 at 21:55






  • 1




    You're welcome! Also you should look into the AnimatedBuilder widget once you've got a good grasp of how Flutter handles animations :)
    – filleduchaos
    Nov 10 at 21:59










  • I will! I saw all kinds of interesting Widgets to experiment with.
    – SEG.Veenstra
    Nov 10 at 22:01













up vote
2
down vote



accepted







up vote
2
down vote



accepted






I'm going to skip your code a bit, and focus on what you're really asking:




The general idea is to make the animations build upon each other with a random new value so for example:




  • first spin: 0 -> 10


  • second spin: 10 -> 13


  • third spin: 13 -> 18


  • ... etc





With an explicit animation like this, there are three objects you are interested in:




  • a controller, which is a special kind of Animation that simply generates values linearly from its lower to its upper bound (both doubles, typically 0.0 and 1.0). You can control the flow of the animation - send it running forward, reverse it, stop it, or reset it.


  • a tween, which isn't an Animation but rather an Animatable. A tween defines the interpolation between two values, which don't even have to be numbers. It implements a transform method under the hood that takes in the current value of an animation and spits out the actual value you want to work with: another number, a color, a linear gradient, even a whole widget. This is what you should use to generate your angles of rotation.


  • an animation, which is the animation whose value you're actually going to work with (so this is where you'd grab values to build with). You get this by giving your tween a parent Animation to transform - this might be your controller directly but can also be some other sort of animation you've built on it (like a CurvedAnimation, which would give you easing or bouncy/elastic curves and so on). Flutter's animations are highly composable that way.



Your code is failing largely because you're not actually using the top-level animation you created in your build method and you're creating a new tween and animation every time you call setNewPosition. You can use the same tween and animation for multiple animation "cycles" - simply change the begin and end properties of the existing tween and it bubbles up to the animation. That ends up something like this:



class _RoulettePageWidgetState extends State<RoulettePageWidget>
with SingleTickerProviderStateMixin {
Animation<double> _animation;
Tween<double> _tween;
AnimationController _animationController;
math.Random _random = math.Random();

int position = 0;

double getRandomAngle() {
return math.pi * 2 / 25 * _random.nextInt(25);
}

@override
void initState() {
super.initState();
_animationController =
AnimationController(duration: Duration(seconds: 2), vsync: this);
_tween = Tween(begin: 0.0, end: getRandomAngle());
_animation = _tween.animate(_animationController)
..addListener(() {
setState(() {});
});
}

void setNewPosition() {
_tween.begin = _tween.end;
_animationController.reset();
_tween.end = getRandomAngle();
_animationController.forward();
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Center(
child: Transform.rotate(
angle: _animation.value,
child: Icon(
Icons.arrow_upward,
size: 250.0,
),
)),
Expanded(
child: Container(),
),
RaisedButton(
child: Text('SPIN'),
onPressed: setNewPosition,
)
],
)
);
}
}


Hope that helps!






share|improve this answer














I'm going to skip your code a bit, and focus on what you're really asking:




The general idea is to make the animations build upon each other with a random new value so for example:




  • first spin: 0 -> 10


  • second spin: 10 -> 13


  • third spin: 13 -> 18


  • ... etc





With an explicit animation like this, there are three objects you are interested in:




  • a controller, which is a special kind of Animation that simply generates values linearly from its lower to its upper bound (both doubles, typically 0.0 and 1.0). You can control the flow of the animation - send it running forward, reverse it, stop it, or reset it.


  • a tween, which isn't an Animation but rather an Animatable. A tween defines the interpolation between two values, which don't even have to be numbers. It implements a transform method under the hood that takes in the current value of an animation and spits out the actual value you want to work with: another number, a color, a linear gradient, even a whole widget. This is what you should use to generate your angles of rotation.


  • an animation, which is the animation whose value you're actually going to work with (so this is where you'd grab values to build with). You get this by giving your tween a parent Animation to transform - this might be your controller directly but can also be some other sort of animation you've built on it (like a CurvedAnimation, which would give you easing or bouncy/elastic curves and so on). Flutter's animations are highly composable that way.



Your code is failing largely because you're not actually using the top-level animation you created in your build method and you're creating a new tween and animation every time you call setNewPosition. You can use the same tween and animation for multiple animation "cycles" - simply change the begin and end properties of the existing tween and it bubbles up to the animation. That ends up something like this:



class _RoulettePageWidgetState extends State<RoulettePageWidget>
with SingleTickerProviderStateMixin {
Animation<double> _animation;
Tween<double> _tween;
AnimationController _animationController;
math.Random _random = math.Random();

int position = 0;

double getRandomAngle() {
return math.pi * 2 / 25 * _random.nextInt(25);
}

@override
void initState() {
super.initState();
_animationController =
AnimationController(duration: Duration(seconds: 2), vsync: this);
_tween = Tween(begin: 0.0, end: getRandomAngle());
_animation = _tween.animate(_animationController)
..addListener(() {
setState(() {});
});
}

void setNewPosition() {
_tween.begin = _tween.end;
_animationController.reset();
_tween.end = getRandomAngle();
_animationController.forward();
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Center(
child: Transform.rotate(
angle: _animation.value,
child: Icon(
Icons.arrow_upward,
size: 250.0,
),
)),
Expanded(
child: Container(),
),
RaisedButton(
child: Text('SPIN'),
onPressed: setNewPosition,
)
],
)
);
}
}


Hope that helps!







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 10 at 21:58

























answered Nov 10 at 21:39









filleduchaos

692




692












  • Not only does this answer my question but your explanation really helps me to understand the whole concept. Funny thing is that I basically had this before I tried creating a new Tween except for reading out the right animation object!
    – SEG.Veenstra
    Nov 10 at 21:55






  • 1




    You're welcome! Also you should look into the AnimatedBuilder widget once you've got a good grasp of how Flutter handles animations :)
    – filleduchaos
    Nov 10 at 21:59










  • I will! I saw all kinds of interesting Widgets to experiment with.
    – SEG.Veenstra
    Nov 10 at 22:01


















  • Not only does this answer my question but your explanation really helps me to understand the whole concept. Funny thing is that I basically had this before I tried creating a new Tween except for reading out the right animation object!
    – SEG.Veenstra
    Nov 10 at 21:55






  • 1




    You're welcome! Also you should look into the AnimatedBuilder widget once you've got a good grasp of how Flutter handles animations :)
    – filleduchaos
    Nov 10 at 21:59










  • I will! I saw all kinds of interesting Widgets to experiment with.
    – SEG.Veenstra
    Nov 10 at 22:01
















Not only does this answer my question but your explanation really helps me to understand the whole concept. Funny thing is that I basically had this before I tried creating a new Tween except for reading out the right animation object!
– SEG.Veenstra
Nov 10 at 21:55




Not only does this answer my question but your explanation really helps me to understand the whole concept. Funny thing is that I basically had this before I tried creating a new Tween except for reading out the right animation object!
– SEG.Veenstra
Nov 10 at 21:55




1




1




You're welcome! Also you should look into the AnimatedBuilder widget once you've got a good grasp of how Flutter handles animations :)
– filleduchaos
Nov 10 at 21:59




You're welcome! Also you should look into the AnimatedBuilder widget once you've got a good grasp of how Flutter handles animations :)
– filleduchaos
Nov 10 at 21:59












I will! I saw all kinds of interesting Widgets to experiment with.
– SEG.Veenstra
Nov 10 at 22:01




I will! I saw all kinds of interesting Widgets to experiment with.
– SEG.Veenstra
Nov 10 at 22:01












up vote
0
down vote













While working, in no situation will you actually want to make these animations within your layout as explained by @filleduchaos.



This is under optimized, as you're rebuilding far more than you should for the animation. And it's a pain to write yourself.



You'll want to use the AnimatedWidget family for this. They are divided into two
kinds:




  • XXTransition

  • AnimatedXX


The first is a low layer that consumes an Animation and listens to it so that you don't need to do that ugly :



..addListener(() {
setState(() {});
});


The second handles the remaining pieces: AnimationController, TickerProvider and Tween.



This makes using animations much easier as it's almost entirely automatical.



In your case a rotation example would be as followed:



class RotationExample extends StatefulWidget {
final Widget child;

const RotationExample({
Key key,
this.child,
}) : super(key: key);

@override
RotationExampleState createState() {
return new RotationExampleState();
}
}

class RotationExampleState extends State<RotationExample> {
final _random = math.Random();
double rad = 0.0;

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _rotate,
child: AnimatedTransform(
duration: const Duration(seconds: 1),
alignment: Alignment.center,
transform: Matrix4.rotationZ(rad),
child: Container(
color: Colors.red,
height: 42.0,
width: 42.0,
),
),
);
}

void _rotate() {
setState(() {
rad = math.pi * 2 / 25 * _random.nextInt(25);
});
}
}


Easier right?



The irony is that Flutter forgot to provide an AnimatedTransform (even although we have many others !). But no worries, I made it for you!



The AnimatedTransform implementation is as followed :



class AnimatedTransform extends ImplicitlyAnimatedWidget {
final Matrix4 transform;
final AlignmentGeometry alignment;
final bool transformHitTests;
final Offset origin;
final Widget child;

const AnimatedTransform({
Key key,
@required this.transform,
@required Duration duration,
this.alignment,
this.transformHitTests = true,
this.origin,
this.child,
Curve curve = Curves.linear,
}) : assert(transform != null),
assert(duration != null),
super(
key: key,
duration: duration,
curve: curve,
);

@override
_AnimatedTransformState createState() => _AnimatedTransformState();
}

class _AnimatedTransformState
extends AnimatedWidgetBaseState<AnimatedTransform> {
Matrix4Tween _transform;

@override
void forEachTween(TweenVisitor<dynamic> visitor) {
_transform = visitor(_transform, widget.transform,
(dynamic value) => Matrix4Tween(begin: value));
}

@override
Widget build(BuildContext context) {
return Transform(
alignment: widget.alignment,
transform: _transform.evaluate(animation),
transformHitTests: widget.transformHitTests,
origin: widget.origin,
child: widget.child,
);
}
}


I will submit a pull request so that in the future you won't need this bit of code.






share|improve this answer























  • Eh, they're clearly working on understanding explicit animations. You don't always want widgets to implicitly animate themselves, and it's better to figure out how the Animation/Animatable stack works with something as easy as doubles.
    – filleduchaos
    Nov 11 at 0:11










  • But in production, this is what you'd want to use instead of the previous code. The fact that he's learning doesn't justify a partial answer.
    – Rémi Rousselet
    Nov 11 at 0:20










  • They're following an official tutorial that's explicitly about explicit animations and asked for help with that. I don't see how explaining why they're stuck on their tutorial about explicit animations is a partial answer.
    – filleduchaos
    Nov 11 at 0:29










  • There literally is the rest of the tutorial right there, which also touches on AnimatedWidget and AnimatedBuilder.
    – filleduchaos
    Nov 11 at 0:31










  • He's not following the tutorial, he's using it as a reference for his own project. But this doesn't matter anyway, the purpose of StackOverflow is to provide helpful answers for the whole world to see. If this helps, then it's fine.
    – Rémi Rousselet
    Nov 11 at 0:38















up vote
0
down vote













While working, in no situation will you actually want to make these animations within your layout as explained by @filleduchaos.



This is under optimized, as you're rebuilding far more than you should for the animation. And it's a pain to write yourself.



You'll want to use the AnimatedWidget family for this. They are divided into two
kinds:




  • XXTransition

  • AnimatedXX


The first is a low layer that consumes an Animation and listens to it so that you don't need to do that ugly :



..addListener(() {
setState(() {});
});


The second handles the remaining pieces: AnimationController, TickerProvider and Tween.



This makes using animations much easier as it's almost entirely automatical.



In your case a rotation example would be as followed:



class RotationExample extends StatefulWidget {
final Widget child;

const RotationExample({
Key key,
this.child,
}) : super(key: key);

@override
RotationExampleState createState() {
return new RotationExampleState();
}
}

class RotationExampleState extends State<RotationExample> {
final _random = math.Random();
double rad = 0.0;

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _rotate,
child: AnimatedTransform(
duration: const Duration(seconds: 1),
alignment: Alignment.center,
transform: Matrix4.rotationZ(rad),
child: Container(
color: Colors.red,
height: 42.0,
width: 42.0,
),
),
);
}

void _rotate() {
setState(() {
rad = math.pi * 2 / 25 * _random.nextInt(25);
});
}
}


Easier right?



The irony is that Flutter forgot to provide an AnimatedTransform (even although we have many others !). But no worries, I made it for you!



The AnimatedTransform implementation is as followed :



class AnimatedTransform extends ImplicitlyAnimatedWidget {
final Matrix4 transform;
final AlignmentGeometry alignment;
final bool transformHitTests;
final Offset origin;
final Widget child;

const AnimatedTransform({
Key key,
@required this.transform,
@required Duration duration,
this.alignment,
this.transformHitTests = true,
this.origin,
this.child,
Curve curve = Curves.linear,
}) : assert(transform != null),
assert(duration != null),
super(
key: key,
duration: duration,
curve: curve,
);

@override
_AnimatedTransformState createState() => _AnimatedTransformState();
}

class _AnimatedTransformState
extends AnimatedWidgetBaseState<AnimatedTransform> {
Matrix4Tween _transform;

@override
void forEachTween(TweenVisitor<dynamic> visitor) {
_transform = visitor(_transform, widget.transform,
(dynamic value) => Matrix4Tween(begin: value));
}

@override
Widget build(BuildContext context) {
return Transform(
alignment: widget.alignment,
transform: _transform.evaluate(animation),
transformHitTests: widget.transformHitTests,
origin: widget.origin,
child: widget.child,
);
}
}


I will submit a pull request so that in the future you won't need this bit of code.






share|improve this answer























  • Eh, they're clearly working on understanding explicit animations. You don't always want widgets to implicitly animate themselves, and it's better to figure out how the Animation/Animatable stack works with something as easy as doubles.
    – filleduchaos
    Nov 11 at 0:11










  • But in production, this is what you'd want to use instead of the previous code. The fact that he's learning doesn't justify a partial answer.
    – Rémi Rousselet
    Nov 11 at 0:20










  • They're following an official tutorial that's explicitly about explicit animations and asked for help with that. I don't see how explaining why they're stuck on their tutorial about explicit animations is a partial answer.
    – filleduchaos
    Nov 11 at 0:29










  • There literally is the rest of the tutorial right there, which also touches on AnimatedWidget and AnimatedBuilder.
    – filleduchaos
    Nov 11 at 0:31










  • He's not following the tutorial, he's using it as a reference for his own project. But this doesn't matter anyway, the purpose of StackOverflow is to provide helpful answers for the whole world to see. If this helps, then it's fine.
    – Rémi Rousselet
    Nov 11 at 0:38













up vote
0
down vote










up vote
0
down vote









While working, in no situation will you actually want to make these animations within your layout as explained by @filleduchaos.



This is under optimized, as you're rebuilding far more than you should for the animation. And it's a pain to write yourself.



You'll want to use the AnimatedWidget family for this. They are divided into two
kinds:




  • XXTransition

  • AnimatedXX


The first is a low layer that consumes an Animation and listens to it so that you don't need to do that ugly :



..addListener(() {
setState(() {});
});


The second handles the remaining pieces: AnimationController, TickerProvider and Tween.



This makes using animations much easier as it's almost entirely automatical.



In your case a rotation example would be as followed:



class RotationExample extends StatefulWidget {
final Widget child;

const RotationExample({
Key key,
this.child,
}) : super(key: key);

@override
RotationExampleState createState() {
return new RotationExampleState();
}
}

class RotationExampleState extends State<RotationExample> {
final _random = math.Random();
double rad = 0.0;

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _rotate,
child: AnimatedTransform(
duration: const Duration(seconds: 1),
alignment: Alignment.center,
transform: Matrix4.rotationZ(rad),
child: Container(
color: Colors.red,
height: 42.0,
width: 42.0,
),
),
);
}

void _rotate() {
setState(() {
rad = math.pi * 2 / 25 * _random.nextInt(25);
});
}
}


Easier right?



The irony is that Flutter forgot to provide an AnimatedTransform (even although we have many others !). But no worries, I made it for you!



The AnimatedTransform implementation is as followed :



class AnimatedTransform extends ImplicitlyAnimatedWidget {
final Matrix4 transform;
final AlignmentGeometry alignment;
final bool transformHitTests;
final Offset origin;
final Widget child;

const AnimatedTransform({
Key key,
@required this.transform,
@required Duration duration,
this.alignment,
this.transformHitTests = true,
this.origin,
this.child,
Curve curve = Curves.linear,
}) : assert(transform != null),
assert(duration != null),
super(
key: key,
duration: duration,
curve: curve,
);

@override
_AnimatedTransformState createState() => _AnimatedTransformState();
}

class _AnimatedTransformState
extends AnimatedWidgetBaseState<AnimatedTransform> {
Matrix4Tween _transform;

@override
void forEachTween(TweenVisitor<dynamic> visitor) {
_transform = visitor(_transform, widget.transform,
(dynamic value) => Matrix4Tween(begin: value));
}

@override
Widget build(BuildContext context) {
return Transform(
alignment: widget.alignment,
transform: _transform.evaluate(animation),
transformHitTests: widget.transformHitTests,
origin: widget.origin,
child: widget.child,
);
}
}


I will submit a pull request so that in the future you won't need this bit of code.






share|improve this answer














While working, in no situation will you actually want to make these animations within your layout as explained by @filleduchaos.



This is under optimized, as you're rebuilding far more than you should for the animation. And it's a pain to write yourself.



You'll want to use the AnimatedWidget family for this. They are divided into two
kinds:




  • XXTransition

  • AnimatedXX


The first is a low layer that consumes an Animation and listens to it so that you don't need to do that ugly :



..addListener(() {
setState(() {});
});


The second handles the remaining pieces: AnimationController, TickerProvider and Tween.



This makes using animations much easier as it's almost entirely automatical.



In your case a rotation example would be as followed:



class RotationExample extends StatefulWidget {
final Widget child;

const RotationExample({
Key key,
this.child,
}) : super(key: key);

@override
RotationExampleState createState() {
return new RotationExampleState();
}
}

class RotationExampleState extends State<RotationExample> {
final _random = math.Random();
double rad = 0.0;

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _rotate,
child: AnimatedTransform(
duration: const Duration(seconds: 1),
alignment: Alignment.center,
transform: Matrix4.rotationZ(rad),
child: Container(
color: Colors.red,
height: 42.0,
width: 42.0,
),
),
);
}

void _rotate() {
setState(() {
rad = math.pi * 2 / 25 * _random.nextInt(25);
});
}
}


Easier right?



The irony is that Flutter forgot to provide an AnimatedTransform (even although we have many others !). But no worries, I made it for you!



The AnimatedTransform implementation is as followed :



class AnimatedTransform extends ImplicitlyAnimatedWidget {
final Matrix4 transform;
final AlignmentGeometry alignment;
final bool transformHitTests;
final Offset origin;
final Widget child;

const AnimatedTransform({
Key key,
@required this.transform,
@required Duration duration,
this.alignment,
this.transformHitTests = true,
this.origin,
this.child,
Curve curve = Curves.linear,
}) : assert(transform != null),
assert(duration != null),
super(
key: key,
duration: duration,
curve: curve,
);

@override
_AnimatedTransformState createState() => _AnimatedTransformState();
}

class _AnimatedTransformState
extends AnimatedWidgetBaseState<AnimatedTransform> {
Matrix4Tween _transform;

@override
void forEachTween(TweenVisitor<dynamic> visitor) {
_transform = visitor(_transform, widget.transform,
(dynamic value) => Matrix4Tween(begin: value));
}

@override
Widget build(BuildContext context) {
return Transform(
alignment: widget.alignment,
transform: _transform.evaluate(animation),
transformHitTests: widget.transformHitTests,
origin: widget.origin,
child: widget.child,
);
}
}


I will submit a pull request so that in the future you won't need this bit of code.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 11 at 0:09

























answered Nov 10 at 23:49









Rémi Rousselet

20.6k23068




20.6k23068












  • Eh, they're clearly working on understanding explicit animations. You don't always want widgets to implicitly animate themselves, and it's better to figure out how the Animation/Animatable stack works with something as easy as doubles.
    – filleduchaos
    Nov 11 at 0:11










  • But in production, this is what you'd want to use instead of the previous code. The fact that he's learning doesn't justify a partial answer.
    – Rémi Rousselet
    Nov 11 at 0:20










  • They're following an official tutorial that's explicitly about explicit animations and asked for help with that. I don't see how explaining why they're stuck on their tutorial about explicit animations is a partial answer.
    – filleduchaos
    Nov 11 at 0:29










  • There literally is the rest of the tutorial right there, which also touches on AnimatedWidget and AnimatedBuilder.
    – filleduchaos
    Nov 11 at 0:31










  • He's not following the tutorial, he's using it as a reference for his own project. But this doesn't matter anyway, the purpose of StackOverflow is to provide helpful answers for the whole world to see. If this helps, then it's fine.
    – Rémi Rousselet
    Nov 11 at 0:38


















  • Eh, they're clearly working on understanding explicit animations. You don't always want widgets to implicitly animate themselves, and it's better to figure out how the Animation/Animatable stack works with something as easy as doubles.
    – filleduchaos
    Nov 11 at 0:11










  • But in production, this is what you'd want to use instead of the previous code. The fact that he's learning doesn't justify a partial answer.
    – Rémi Rousselet
    Nov 11 at 0:20










  • They're following an official tutorial that's explicitly about explicit animations and asked for help with that. I don't see how explaining why they're stuck on their tutorial about explicit animations is a partial answer.
    – filleduchaos
    Nov 11 at 0:29










  • There literally is the rest of the tutorial right there, which also touches on AnimatedWidget and AnimatedBuilder.
    – filleduchaos
    Nov 11 at 0:31










  • He's not following the tutorial, he's using it as a reference for his own project. But this doesn't matter anyway, the purpose of StackOverflow is to provide helpful answers for the whole world to see. If this helps, then it's fine.
    – Rémi Rousselet
    Nov 11 at 0:38
















Eh, they're clearly working on understanding explicit animations. You don't always want widgets to implicitly animate themselves, and it's better to figure out how the Animation/Animatable stack works with something as easy as doubles.
– filleduchaos
Nov 11 at 0:11




Eh, they're clearly working on understanding explicit animations. You don't always want widgets to implicitly animate themselves, and it's better to figure out how the Animation/Animatable stack works with something as easy as doubles.
– filleduchaos
Nov 11 at 0:11












But in production, this is what you'd want to use instead of the previous code. The fact that he's learning doesn't justify a partial answer.
– Rémi Rousselet
Nov 11 at 0:20




But in production, this is what you'd want to use instead of the previous code. The fact that he's learning doesn't justify a partial answer.
– Rémi Rousselet
Nov 11 at 0:20












They're following an official tutorial that's explicitly about explicit animations and asked for help with that. I don't see how explaining why they're stuck on their tutorial about explicit animations is a partial answer.
– filleduchaos
Nov 11 at 0:29




They're following an official tutorial that's explicitly about explicit animations and asked for help with that. I don't see how explaining why they're stuck on their tutorial about explicit animations is a partial answer.
– filleduchaos
Nov 11 at 0:29












There literally is the rest of the tutorial right there, which also touches on AnimatedWidget and AnimatedBuilder.
– filleduchaos
Nov 11 at 0:31




There literally is the rest of the tutorial right there, which also touches on AnimatedWidget and AnimatedBuilder.
– filleduchaos
Nov 11 at 0:31












He's not following the tutorial, he's using it as a reference for his own project. But this doesn't matter anyway, the purpose of StackOverflow is to provide helpful answers for the whole world to see. If this helps, then it's fine.
– Rémi Rousselet
Nov 11 at 0:38




He's not following the tutorial, he's using it as a reference for his own project. But this doesn't matter anyway, the purpose of StackOverflow is to provide helpful answers for the whole world to see. If this helps, then it's fine.
– Rémi Rousselet
Nov 11 at 0:38


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53243077%2fwhat-would-be-the-proper-way-to-update-animation-values-in-a-flutter-animation%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Full-time equivalent

さくらももこ

13 indicted, 8 arrested in Calif. drug cartel investigation