Reputation: 61
My app contains a couple of pages. In the appbar I have a selfmade stateful widget with a badge that shows the number of new messages. When I swipe to refresh data the badge will run a small animation if the badge value is changed.
The problem is that the badge value comes from a scoped model. How do I run the animation from the scoped model class. I tried to let the scoped model class hold the animationController as well as a function. It works on the first and second screen. But when I am navigating back to the first page again and pull to refresh. It is like the animationController is in bad state.
Code in the scoped model:
Function _runNotificationAnimation;
set runNotificationAnimation(Function fun) => _runNotificationAnimation = fun;
void _setNotificationCount(int count) {
_notificationCount = count;
if (count > 0 && _runNotificationAnimation != null) {
_runNotificationAnimation();
}
notifyListeners();
}
function that runs the animation
runAnim() {
setState(() {
controller.reset();
controller.forward(from: 0.0);
});
}
Error from flutter:
[VERBOSE-2:shell.cc(184)] Dart Error: Unhandled exception: NoSuchMethodError: The method 'stop' was called on null. Receiver: null Tried calling: stop(canceled: true) 0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5) 1 AnimationController.stop (package:flutter/src/animation/animation_controller.dart:650:13) 2 AnimationController.value= (package:flutter/src/animation/animation_controller.dart:349:5) 3 AnimationController.reset (package:flutter/src/animation/animation_controller.dart:370:5) 4 NotificationIconState.runAnim (package:volvopenta/widgets/notificaton_icon.dart:38:16) 5 SettingsModel._setNotificationCount (package:volvopenta/scoped-models/settings-model.dart:57:7) 6 SettingsModel.updateAppData (package:volvopenta/scoped-models/settings-model.dart:185:5) 7 MyMachines.build... (package:volvopenta/pages/fleet.dart:83:27) 8<…>
Upvotes: 1
Views: 517
Reputation: 2340
Since your animation will be built in a stateful Widget, it is better to leave the animationController in that stateful Widget and move only the animation (Tween) in the model class. It is essential that you place the notifyListener(); in the controller.addListerner() and not at the end of the function.
class MyModel extends Model{
Animation animation;
runAnimation(controller) {
animation = Tween(begin: 0,0, end:
400).animate(controller);
controller.forward();
controller.addListener((){
notifyListeners();
});
}
}
You can call this function in your stateful widget as follows:
class _MyScreenState extends State<MyScreen> with
SingleTickerProviderStateMixin{
AnimationController controller;
MyModel myModel = MyModel();
@overide
void initState(){
super.initState();
controller = AnimationController(duration: Duration(seconds: 2), vsync:
this);
myModel.runAnimation(controller);
}
//dispose here
@override
Widget build(Buildcontext context){
return ScopedModel<MyModel>(
model: myModel,
child: Scaffold(
body: Text("Hello", style: TextStyle(fontSize: 13 *
controller.value)),
),
);
}
}
Upvotes: 1