user1295782
user1295782

Reputation: 61

Flutter - Running animation from scoped model

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

Answers (1)

Lo&#239;c Fonkam
Lo&#239;c Fonkam

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

Related Questions