A Flutter library that makes animation easer. It allows for separation of animation setup from the User Interface.

Related tags

Animation animator
Overview

animator

pub package actions workflow codecov

This library is an animation library for Flutter that:

  • makes animation as simple as the simplest widget in Flutter with the help of Animator widget,
  • Allows you to control (forward, stop, inverse), reconfigure, reset and restart animation from buttons, or events callbacks.
  • Perform implicit and explicit animation without limitation.

This library exposes two widgets, Animator, ane AnimateWidget

  • Animator is the first introduced widget. It allows for explicit animation.
  • AnimateWidget the the new widget which is more powerful than Animator. It is used for both implicit animation and explicit and staggered animation.

AnimateWidget

setting animation parameters

AnimateWidget exposes the following parameters to set your animation:

AnimateWidget({
    Key? key, 
    double? initialValue, // (1)
    double lowerBound = 0.0, // (1)
    double upperBound = 1.0, // (1)

    Duration duration = const Duration(milliseconds: 500),  // (2)
    Duration? reverseDuration,  // (2)

    Curve curve = Curves.linear,  // (3)
    Curve? reverseCurve, // (3)

    AnimationBehavior animationBehavior = AnimationBehavior.normal, // (4)

    int? repeats, // (5)
    int? cycles, // (5)

    void Function()? endAnimationListener, // (6)

    bool triggerOnInit = true, // (7)
    bool triggerOnRebuild = false, // (7)
    bool resetOnRebuild = false, // (7)
    required Widget Function(BuildContext, Animate) builder,// (8)
  }
)
  • (1) Optionally you can set the initialValue, lowerBound, upperBound to be taken by the AnimationController.
  • (2) duration and reverseDuration are the global (default) durations of the animation in the forward and reverse path. If reverseDuration is not set (or is null) the value of duration will be used for both forward and reverse path. The value of duration and reverseDuration can be overridden for any value. (see later).
  • (3) curve and reverseCurve are the global (default) curves of the animation in the forward and reverse path. If reverseCurve is not set (or is null) the value of curve will be used for both forward and reverse path. The value of curve and reverseCurve can be overridden for any value. (see later).
  • (4) animationBehavior has similar meaning as in Flutter animationBehavior (The behavior of the controller when AccessibilityFeatures.disableAnimations is true).
  • With cycles argument (5) you define the number of the forward and backward periods you want your animation to perform before stopping.
  • With repeats argument (5) you define the number of forward periods you want your animation to perform before stopping.
  • With endAnimationListener (6) argument you can define a VoidCallback to be executed when the animation is finished. For example, it can be used to trigger another animation.
  • You can control when animation starts (7) using :
    • triggerOnInt: When set to true, animation will auto start after first initialized. The default value is true.
    • triggerOnRebuild: When set to true, animation will try to trigger on rebuild. If animation is completed (stopped at the upperBound) then the animation is reversed, and if the animation is dismissed (stopped at the lowerBound) then the animation is forwarded. IF animation is running nothing will happen. Default value is false.
    • resetOnRebuild: When set to true, animation will reset and restart from its lowerBound.
  • In the builder argument (8) you put your widgets to be animated.
        AnimateWidget(
          builder : (BuildContext context, Animate animate) {
              //Implicit animation
              final T value =  animate.call(select? 0 : 100);
              ///Two value of the same type must be distinguished using an arbitrary name
              final T otherValue =  animate.call(select? 0 : 100, 'Other value');
    
    
              //Explicit animation
              final T value =  animate.fromTween((currentValue)=> Tween(begin:0, end: 100));
    
              //Use predefined flutter FooTransition widget
              ScaleTransition(
                scale : animate.curvedAnimation
                child: ...
              )
          },
          child : MayWidget(), //widget to not rebuild with animation
      )

Implicit animation

With animator you can do any kind of implicit animation without been constrained to fined a dedicated Flutter widget of type AnimatedFoo such as AnimatedContainer, AnimatedPositioned and so on.

Let's reproduce the AnimatedContainer example in official Flutter docs. (link here).

In Flutter AnimatedContainer example, we see:

Center(
    child: AnimatedContainer(
        duration: const Duration(seconds: 2),
        curve: Curves.fastOutSlowIn,
        width: selected ? 200.0 : 100.0,
        height: selected ? 100.0 : 200.0,
        color: selected ? Colors.red : Colors.blue,
        alignment: selected ? Alignment.center : AlignmentDirectional.topCenter,
        child: const FlutterLogo(size: 75),
    ),
),

With animateWidget, we simply use the Container` widget :

Center(
    child: AnimatedWidget(
        duration: const Duration(seconds: 2),
        curve: Curves.fastOutSlowIn,
        (context, animate) => Container(
            // Animate is a callable class
            width: animate.call(selected ? 200.0 : 100.0),
            height: animate(selected ? 100.0 : 200.0, 'height'),
            color: animate(selected ? Colors.red : Colors.blue),
            alignment: animate(selected ? Alignment.center : AlignmentDirectional.topCenter),
            child: const FlutterLogo(size: 75),
        ),
    );
),
  • Using the exposed animate function, we set the animation start and end values.
  • As the width and height are the same type (double), we need to add a name to distinguish them.

You can implicitly animate any type. Here we implicitly animated a double, Color, and Alignment values. If you want to animate two parameters of the same type, you just add a dummy name to distinguish them.

That's all, you are not limited to use a widget that starts with Animated prefix to use implicit animation.

Here is the full working example.

Explicit animation

In explicit animation you have full control on how to parametrize your animation using tweens.

AnimatedWidget(
    duration: const Duration(seconds: 2),
    (context, animate) {
      final angle = animate.fromTween(
          (currentValue) => Tween(begin: 0, end: 2 * 3.14),
      )!;

      return Transform.rotate(
        angle: angle,
        child: const FlutterLogo(size: 75),
      );
    },
);
  • The FlutterLogo will rotate from 0 to 2 * 3.14 (one turn)
  • The fromTween exposes the current value of the angle. It may be used to animate from the current value to the next value. (See the example below)

Here is the full working example.

Use of Flutter's transition widgets

You can use built-in flutter's FooTransition widget such as PositionedTransition, AlignTransition ..:

The following example is the same example of PositionedTransition in flutter docs rewritten using states_rebuilder. (Link here).

 AnimateWidget(
   (context, animate) => PositionedTransition(
     rect: RelativeRectTween(
       begin: RelativeRect.fromSize( const Rect.fromLTWH(0, 0, smallLogo, smallLogo), biggest),
       end: RelativeRect.fromSize(
         Rect.fromLTWH(
           biggest.width - bigLogo, biggest.height - bigLogo, bigLogo, bigLogo),
           biggest),
     ).animate(animate.curvedAnimation),
     child: const Padding(padding: EdgeInsets.all(8), child: FlutterLogo()),
   ),
 );

Here is the full working example.

For rebuild performance use Child, Child2 and Child3 widget.

Here an example of clock app.

staggered Animation

You can specify for each animate value, its onw curve and reverseCurve using setCurve and setReverseCurve.

This is the same example as in Flutter docs for staggered animation:

class _MyStaggeredWidgetState extends State<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onTap: () {
        setState(() {});
      },
      child: AnimateWidget(
        duration: const Duration(milliseconds: 2000),
        cycles: 2,
        triggerOnRebuild: true,
        triggerOnInit: false,
        builder: (context, animate) {
          final padding = animate
              .setCurve(Interval(0.250, 0.375, curve: Curves.ease))
              .fromTween(
                (_) => EdgeInsetsTween(
                  begin: const EdgeInsets.only(bottom: 16.0),
                  end: const EdgeInsets.only(bottom: 75.0),
                ),
              );
          final opacity = animate
              .setCurve(Interval(0.0, 0.100, curve: Curves.ease))
              .fromTween(
                (_) => Tween<double>(begin: 0.0, end: 1.0),
              )!;
          final containerWidget = animate
              .setCurve(Interval(0.125, 0.250, curve: Curves.ease))
              .fromTween(
                (_) => Tween<double>(begin: 50.0, end: 150.0),
                'width',
              )!;
          final containerHeight = animate
              .setCurve(Interval(0.250, 0.375, curve: Curves.ease))
              .fromTween(
                (_) => Tween<double>(begin: 50.0, end: 150.0),
                'height',
              )!;
          final color = animate
              .setCurve(Interval(0.500, 0.750, curve: Curves.ease))
              .fromTween(
                (_) => ColorTween(
                  begin: Colors.indigo[100],
                  end: Colors.orange[400],
                ),
              );
          final borderRadius = animate
              .setCurve(Interval(0.375, 0.500, curve: Curves.ease))
              .fromTween(
                (_) => BorderRadiusTween(
                  begin: BorderRadius.circular(4.0),
                  end: BorderRadius.circular(75.0),
                ),
              );
          return Center(
            child: Container(
              width: 300.0,
              height: 300.0,
              decoration: BoxDecoration(
                color: Colors.black.withOpacity(0.1),
                border: Border.all(
                  color: Colors.black.withOpacity(0.5),
                ),
              ),
              child: Container(
                padding: padding,
                alignment: Alignment.bottomCenter,
                child: Opacity(
                  opacity: opacity,
                  child: Container(
                    width: containerWidget,
                    height: containerHeight,
                    decoration: BoxDecoration(
                      color: color,
                      border: Border.all(
                        color: Colors.indigo[300]!,
                        width: 3.0,
                      ),
                      borderRadius: borderRadius,
                    ),
                  ),
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

Here is the full working example.

One of the particularities of Animator is that you can use staggered animation with implicitly animated widget. Here is the above example with implicit staggered animation

Examples:

̉# Animator:

With one widget, Animator, you can do all the available animation in Flutter.

Actually, Animator is a facade that hides all the complexity of the animation setting in Flutter. In the design pattern the facade pattern is :

Facade is a structural design pattern that provides a simplified interface to a library, a framework, or any other complex set of classes.

Animator({
  Key key, 
  Tween<dynamic> tween, // (1) // Default tween: Tween<double>(begin:0 end: 1)
  Map<String, Tween<dynamic>> tweenMap, // (1)
  Duration duration: const Duration(milliseconds: 500),  // (2)
  Curve curve: Curves.linear, // (3)
  int cycles, // (4)
  int repeats, // (5)
  (BuildContext, AnimatorState, child) → Widget builder, // (6)
  Widget child, // (7)
  () → void endAnimationListener, // (8)
  dynamic customListener,  // (9)
  (AnimationStatus, AnimationSetup) → dynamic statusListener //(10)
  bool triggerOnInit: true, () // (11)
  bool resetAnimationOnRebuild: false, // (12)
  TickerMixin tickerMixin, // (13)
  AnimatorKey animatorKey, // (14)
})
  • To implement any type of animation with animator you have to define a Tween (1), Duration (2), and Curve (3). `

  • With cycles argument (4) you define the number of the forward and backward periods you want your animation to perform before stopping.

  • With repeats argument (5) you define the number of forward periods you want your animation to perform before stopping.

  • In the builder argument (6) you put your widgets to be animated.

        Animator<T>(
          builder : (BuildContext context, AnimatorState animatorState, Widget child) {
              //to get animation value:
              final T value =  animatorState.value;
              //to get Animation object:
              final Animation<T> animation = animatorState.animation;
              //to get AnimationController object:
              final AnimationController animation = animatorState.controller;
              //to get animation value form tweenMap
              final R value = animatorState.getValue<R>('animName');
              //To get Animation object from tweenMap
              final Animation<R> value =animatorState.getAnimation<R>('animName');
          },
          child : MayWidget(), //widget to not rebuild with animation
      )
  • If you want to animate many Tween, use tweenMap argument (2). It is a Map of String type keys and Tween type values.

  • With endAnimationListener (8) argument you can define a VoidCallback to be executed when the animation is finished. For example, it can be used to trigger another animation.

  • With customListener (9) argument you can define a function to be called every time the animation value changes. The customListener is provided with an Animation object.

  • With statusListener (10) argument, you can define a function to be called every time the status of the animation change. The customListener is provided with an AnimationStatus, AnimationSetup objects.

  • triggerOnInit (11) controls whether the animation is automatically started when the Animator widget is initialized. The default value is true.

  • If you want to reset your animation, such as changing your Tween or duration, and want the new setting to be reconsidered when the Animator widget is rebuilt, set the resetAnimationOnRebuild (12) argument to true. The default value is false. (See AnimatorKey)

  • The right TickerProvider is chosen by animator:(13)

    • If animation is simple the singleTickerProviderStateMixin.
    • If you define the animatorKey parameter or set resetAnimationOnRebuild, animator use tickerProviderStateMixin.
  • With animationKey (14), you can associate an Animator widget to an AnimatorKey. Doing so, you can control (forward, start, stop, reverse) animation from callbacks outside the Animator widget, you can even reset the animation parameter (tween, duration curve, repeats, cycles) on the fly. (See example below)

Example of a single Tween animation:

import 'package:flutter/material.dart';
import 'package:animator/animator.dart';

void main() => runApp(AnimatedLogo());

class AnimatedLogo extends StatelessWidget {
  Widget build(BuildContext context) {
    return Animator<double>(
      tween: Tween<double>(begin: 0, end: 300),
      cycles: 0,
      builder: (context, animatorState, child ) => Center(
            child: Container(
              margin: EdgeInsets.symmetric(vertical: 10),
              height: animatorState.value,
              width: animatorState.value,
              child: FlutterLogo(),
            ),
          ),
    );
  }
}

Example of a multi-tween animation:

import 'package:flutter/material.dart';
import 'package:animator/animator.dart';

void main() => runApp(AnimatedLogo());

class AnimatedLogo extends StatelessWidget {
  Widget build(BuildContext context) {
    return Animator(
      tweenMap: {
        "scaleAnim": Tween<double>(begin: 0, end: 300),
        "translateAnim": Tween<Offset>(begin: Offset.zero, end: Offset(2, 0)),
      },
      cycles: 0,
      builder: (context, animatorState, child ) => Center(
            child: FractionalTranslation(
              translation: animatorState.getAnimation<double>('translateAnim'),
              child: Container(
                margin: EdgeInsets.symmetric(vertical: 10),
                height: animatorState.getAnimation<Offset>('scaleAnim'),
                width:  animatorState.getAnimation<Offset>('scaleAnim'),
                child: FlutterLogo(),
              ),
            ),
          ),
    );
  }
}

You can nest many animators with a different setting (tween, duration, curve, repeats, and cycles) to do a complex animation:

This is a simple example of how to animate the scale and rotation independently.

import 'package:flutter/material.dart';
import 'package:animator/animator.dart';

void main() => runApp(AnimatedLogo());

class AnimatedLogo extends StatelessWidget {
  Widget build(BuildContext context) {
    return Animator<double>(
      tween: Tween<double>(begin: 0, end: 300),
      repeats: 0,
      duration: Duration(seconds: 2),
      builder: (context, anim1, child ) => Animator<double>(
        tween: Tween<double>(begin: -1, end: 1),
        cycles: 0,
         builder: (context, anim2, child ) => Center(
          child: Transform.rotate(
            angle: anim2.value,
            child: Container(
              margin: EdgeInsets.symmetric(vertical: 10),
              height: anim1.value,
              width: anim1.value,
              child: FlutterLogo(),
            ),
          ),
        ),
      ),
    );
  }
}

Use nested Animators with CustomPainter and CustomClipper and draw the animation you want.

AnimatorKey

Similarly to Flutter global key. AnimatorKey allows controlling the animation from outside the Animator widget it is associated with.

Example:

final animatorKey = AnimatorKey();

//..
//..
Animator(
    animatorKey: animatorKey,
    builder: (context, anim, child) {
        //....
    }
)

//By default, the animation will not start when the Animator is inserted in the widget tree.
//To start the animation from some Button in the widget tree outside the builder of the Animator.

onPressed: (){
    animatorKey.triggerAnimation();

    //You can  forward, start, reverse animation
    animatorKey.controller.stop,
    

    //You can configure the animation online and reset the setting and restart the animation
    animatorKey.refreshAnimation(
        tween: Tween(...),//new tween
        duration : Duration(...),
        curve : Curve(...),
        repeats : ....,
        cycles : ...
    );

}

AnimatorRebuilder widget

The AnimatorRebuilder widget can subscribe to an “AnimatorKey”. It will be animated in synchronization with the Animator widget with which animatorKey is associated. Example:

//In AnimatorKey you can provide the initial values of the animation.
final animatorKey = AnimatorKey<T>(initialValue: 10);

//..
//..
Animator(
    animatorKey: animatorKey,
    builder: (context, anim, child) {
        //....
    }
);
//

//In another place in the widget tree : 

AnimatorRebuilder(
    observe:()=> animatorKey,
    builder: (context, anim, child) {
        //....
        //this widget receives the same animation object of the Animator above.
    }
);

The order of Animator and AnimatorRebuilder in the widget tree is irrelevant, except in the case, AnimatorRebuilder is first inserted in the widget tree, you have to provide initial values in AnimatorKey to avoid null exceptions.

Example of Flutter log random walk

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:animator/animator.dart';

class RandomFlutterWalk extends StatefulWidget {
  @override
  _RandomFlutterWalkState createState() => _RandomFlutterWalkState();
}

class _RandomFlutterWalkState extends State<RandomFlutterWalk> {
  double beginX = 0.0;
  double beginY = 0.0;
  double endX = Random().nextDouble() * 50;
  double endY = Random().nextDouble() * 50;
  int seconds = Random().nextInt(1000);

  @override
  Widget build(BuildContext context) {
    final screenSize = MediaQuery.of(context).size;
    return Scaffold(
      body: Animator<Offset>(
        tween: Tween<Offset>(
            begin: Offset(beginX, beginY), end: Offset(endX, endY)),
        duration: Duration(milliseconds: 500 + seconds),
        curve: seconds % 2 == 0 ? Curves.linear : Curves.easeInOut,
        resetAnimationOnRebuild: true,
        triggerOnInit: true,
        cycles: 1,
        builder: (_, animatorState, __) => Transform.translate(
          offset: animatorState.value,
          child: FlutterLogo(
            size: 50,
          ),
        ),
        statusListener: (status, setup) {
          if (status == AnimationStatus.completed) {
            setState(() {
              final sign = Random().nextBool() ? 1 : -1;
              beginX = endX;
              beginY = endY;
              double nextEndX = endX + sign * Random().nextDouble() * 50;
              double nextEndY = endY + sign * Random().nextDouble() * 50;

              nextEndX = nextEndX > screenSize.width - 50
                  ? screenSize.width - 50
                  : nextEndX;
              nextEndX = nextEndX < 0 ? 0 : nextEndX;
              nextEndY = nextEndY > screenSize.height - 50
                  ? screenSize.width - 50
                  : nextEndY;
              nextEndY = nextEndY < 0 ? 0 : nextEndY;

              endX = nextEndX;
              endY = nextEndY;
              seconds = Random().nextInt(8);
            });
          }
        },
      ),
    );
  }
}
Comments
  • Exception when Animation gets updates

    Exception when Animation gets updates

    I get an many exceptions when my Animations get updated:

    When the exception was thrown, this was the stack: 
    #0      StatesRebuilder.rebuildStates.<anonymous closure> (package:states_rebuilder/src/states_rebuilder.dart:120:9)
    #1      StatesRebuilder.rebuildStates (package:states_rebuilder/src/states_rebuilder.dart:150:6)
    #2      StatesRebuilderWithAnimator._addAnimationListeners.<anonymous closure> (package:animator/src/states_rebuilder_with_animator.dart:81:7)
    #3      AnimationLocalListenersMixin.notifyListeners (package:flutter/src/animation/listener_helpers.dart:124:19)
    #4      AnimationController._animateToInternal (package:flutter/src/animation/animation_controller.dart:584:9)
    ...
    The AnimationController notifying listeners was: AnimationController#65571(⏮ 1.000; paused)
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    
    ════════ (2) Exception caught by animation library ═════════════════════════════════════════════════
    Exception: 
    ***No observer is subscribed yet***
    | There is no observer subscribed to this observable StatesRebuilderWithAnimator<double> model.
    | To subscribe a widget you use:
    | 1- StateRebuilder for an already defined:
    |   ex:
    |   StatesRebuilder(
    |     models: [StatesRebuilderWithAnimator<double>instance],
    |     builder : ....
    |   )
    | 2- Injector.get<StatesRebuilderWithAnimator<double>>(context : context). for explicit reactivity.
    | 3- Injector.getAsReactive<StatesRebuilderWithAnimator<double>>(context : context). for implicit reactivity.
    | 4- StateRebuilder for new reactive environment:
    |   ex:
    |   StatesRebuilder<StatesRebuilderWithAnimator<double>>(
    |     builder : ....
    |   )
    | 5 - StatesWithMixinBuilder. similar to StateBuilder.
    | 
    | To silent this error you check for the existence of observers before calling [rebuildStates]
    | ex:
    |  if(hasObservers){
    |    rebuildStates()
    | }
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    

    I update all my animation in this class and I am not sure what I should do to address the exception from the Animation Library. Also the stream might update when the previous Animation is not done yet.

    class StreamAnimatorBuilder<T extends Unit> extends StatelessWidget {
      final StreamValue<T> streamValue;
      final Widget Function(double) builder;
      final Duration Function() durationCallback;
      //final Duration animationDuration;
      final Curve curve;
    
      StreamAnimatorBuilder(
          {@required this.streamValue,
          @required this.builder,
          @required this.durationCallback,
          this.curve = Curves.easeInOut});
    
      @override
      Widget build(BuildContext context) => StreamBuilder<T>(
            stream: streamValue.stream,
            initialData: null,
            builder: (context, snapshot) {
              Unit previous = streamValue.previousValue;
              double previousValue = double.parse(previous.value);
              Unit newValue = streamValue.value;
              double value = double.parse(newValue.value);
    
              if (snapshot.data == null ||
                  snapshot.hasError ||
                  previous == null ||
                  newValue == null) {
                return Container();
              } else {
                //print("ANIMATION VALUES: $previousValue , $value");
    
                return Animator(
                    resetAnimationOnRebuild: true,
                    tween: Tween<double>(begin: previousValue, end: value),
                    cycles: 1,
                    duration: durationCallback(),
                    curve: curve,
                    builder: (anim) => builder(anim.value));
              }
            },
          );
    }
    

    Here is an example how I use the class above:

      Widget _renderAnimatedLinearProgress(
              BuildContext context, ValueDecoderBloc<Unit> bloc) =>
          StreamAnimatorBuilder<Unit>(
            streamValue: bloc.valueStream,
            durationCallback: () => Duration(
              milliseconds: int.parse(
                  BlocProvider.of(context).elmBloc.pidUpdateRateBloc.value.value),
            ),
            builder: (value) => CustomPaint(
              painter: LinearProgressPainter(
                value: _calculateValue(value, bloc),
              ),
            ),
          );
    

    Here is a more detailed description is needed: https://medium.com/@ride4sun/flutter-animations-with-the-bloc-pattern-in-6-lines-of-code-53dbb2cba3da

    opened by ride4sun 22
  • Compiler error - Method not found: 'StatesRebuilder.addToListeners'

    Compiler error - Method not found: 'StatesRebuilder.addToListeners'

    Hello,

    I got this compiler error trying to use animator for the first time :

    Compiler message: /C:/Users/..../animator-0.1.4/lib/animator.dart:494:27: Error: Method not found: 'StatesRebuilder.addToListeners'.

    I'm using : Flutter: 1.9.1+hotfix.1 rxdart: ^0.22.2 animator: ^0.1.4

    This issue is related in Health issues and suggestions of this page : https://pub.dev/packages/animator?source=post_page-----e378e82b2508----------------------#-analysis-tab-

    Any idea ?

    Thanks for your awesome job !

    opened by philesc 7
  • Support null safety

    Support null safety

    The library 'package:flutter_animator/flutter_animator.dart' is legacy, and should not be imported into a null safe library. Try migrating the imported library.

    Error: This project cannot run with sound null safety, because one or more project dependencies do not support null safety:

    • package:flutter_animator

    dependencies: animator: ^2.0.2

    opened by md84419 6
  • I can't get an implicit animation to work

    I can't get an implicit animation to work

    All I want to be able to do is run a translation if a variable is true and a different translation if a variable is false

    with implicit animations, it's expected that you can simply change the variable and the change will be made in my case, the variable change is detected by an animated builder the animated builder is indeed catching the change and tween indeed is being updated but the animator isn't performing the animation

    if you could provide an example of how to do this that would be great... in flutter doing something like this with the animated container color takes seconds

    I would imagine if this plugin has the capabilities I expect it should take around the same time

    hopefully, it isn't too much work

    opened by b-cancel 6
  • Duration doesn't seem to reset on windows device 1.0.0+5

    Duration doesn't seem to reset on windows device 1.0.0+5

    This will work for the first 10 seconds when the application starts and then, it will act as if duration is 0 seconds. Here a tween gets updated:

    void _updateScale() {
        setState(() {
            if(zoomed) {
              scaleAnimation = new Tween<double>(begin:2.0, end:1.0);
            } else {
              scaleAnimation = new Tween<double>(begin:1.0, end:2.0);
            }
            zoomed = !zoomed;
        });
      } 
    

    Then, here is the main part of a build function:

    GestureDetector(
                          onDoubleTap: _updateScale,
                          child: Animator(
                              curve: Curves.linear,
                              tween: scaleAnimation,
                              duration: const Duration(seconds:10),
                              cycles: 1,
                              builder: (anim) => Transform.scale(
                                scale: anim.value,
                                child: Text('hey'),
                                 ),
                           ),
    ),
    
    opened by pbuteau 5
  • set scale size for Curves.elasticOut

    set scale size for Curves.elasticOut

    in this code how can i set scale in/out size for animation, i want to implementing this animation:

    Animator(
      duration: Duration(seconds: 1),
      curve: Curves.elasticOut,
      cycles:0,
      builder: (anim) {
        return Transform.scale(
          origin: Offset(0.0, 0.0),
          scale: anim.value,
          child: CircleAvatar(
            radius: 30,
            backgroundColor: Colors.white,
            foregroundColor: Colors.black,
            backgroundImage: NetworkImage(
              "https://images.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png",
            ),
          ),
        );
      },
    )
    
    opened by pishguy 5
  • runtime error after updating to Flutter 1.9 and animator 1.0

    runtime error after updating to Flutter 1.9 and animator 1.0

    (10993): 2642 2019-09-11 11:14:38.719961 SEVERE home_test.sentry_error_reporter: Context: building StateWithMixinBuilder(state: _StateBuilderStateSingleTickerMix#1aa60(ticker inactive)), library: widgets library I/flutter (10993): error: _StateBuilderStateSingleTickerMix is a SingleTickerProviderStateMixin but multiple tickers were created. I/flutter (10993): A SingleTickerProviderStateMixin can only be used as a TickerProvider once. If a State is used for multiple AnimationController objects, or if it is passed to other objects and those objects might use it more than one time in total, then instead of mixing in a SingleTickerProviderStateMixin, use a regular TickerProviderStateMixin. I/flutter (10993): #0 SingleTickerProviderStateMixin.createTicker. (package:flutter/src/widgets/ticker_provider.dart:85:7) I/flutter (10993): #1 SingleTickerProviderStateMixin.createTicker (package:flutter/src/widgets/ticker_provider.dart:92:6) I/flutter (10993): #2 new AnimationController (package:flutter/src/animation/animation_controller.dart:245:21) I/flutter (10993): #3 Animate.setController (package:animator/src/animate.dart:35:18) I/flutter (10993): #4 StatesRebuilderWithAnimator.initAnimation (package:animator/src/states_rebuilder_with_animator.dart:54:14) I/flutter (10993): #5 _AnimatorState.build. (package:animator/src/animator.dart:174:23) I/flutter (10993): #6 _StateBuilderStateSingleTickerMix.build. (package:states_rebuilder/src/state_with_mixin_builder.dart) I/flutter (10993): #7 _StateBuilderState.initState (package:states_rebuilder/src/state_builder.dart:146:42) I/flutter (10993): #8 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4068:58) I/flutter (10993): #9 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3919:5) I/flutter (10993): #10 Element

    all my animations are wrapped in this class:

    import 'package:elm_bluetooth_bloc/model/units/unit.dart';
    import 'package:flutter/material.dart';
    import 'package:utilities/utilities.dart' show StreamValue;
    
    class StreamAnimatorBuilder<T extends Unit> extends StatelessWidget {
      final StreamValue<T> streamValue;
      final Widget Function(double) builder;
      final Duration animationDuration;
      final Curve curve;
    
      StreamAnimatorBuilder(
          {@required this.streamValue,
          @required this.builder,
          this.animationDuration = const Duration(milliseconds: 250),
          this.curve = Curves.easeInOut});
    
      @override
      Widget build(BuildContext context) => StreamBuilder<T>(
            stream: streamValue.stream,
            initialData: null,
            builder: (context, snapshot) {
              Unit previous = streamValue.previousValue;
              double previousValue = double.parse(previous.value);
              Unit newValue = streamValue.value;
              double value = double.parse(newValue.value);
    
              if (snapshot.data == null ||
                  snapshot.hasError ||
                  previous == null ||
                  newValue == null) {
                return Container();
              } else {
    
                //print("ANIMATION VALUES: $previousValue , $value");
    
                return Animator(
                    resetAnimationOnRebuild: true,
                    tween: Tween<double>(begin: previousValue, end: value),
                    cycles: 1,
                    duration: animationDuration,
                    curve: curve,
                    builder: (anim) => builder(anim.value));
              }
            },
          );
    }
    

    If I downgrade animator to 0.1.1 and stay on 1.9 I get this build errors:

    Launching lib\main.dart on moto g 7 in debug mode...
    Initializing gradle...
    Resolving dependencies...
    Running Gradle task 'assembleDebug'...
    registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
    registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
    registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
    
    Compiler message:
    /C:/Users/ride4/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/animator-0.1.4/lib/animator.dart:494:27: Error: Method not found: 'StatesRebuilder.addToListeners'.
              StatesRebuilder.addToListeners(
                              ^^^^^^^^^^^^^^
    /C:/Users/ride4/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/animator-0.1.4/lib/animator.dart:559:27: Error: Method not found: 'StatesRebuilder.removeFromListeners'.
              StatesRebuilder.removeFromListeners(b, widget.name, "$hashCode");
                              ^^^^^^^^^^^^^^^^^^^
    Compiler failed on C:\Projects\obdchk\lib\main.dart
    Finished with error: Gradle task assembleDebug failed with exit code 1
    
    opened by ride4sun 4
  • Simply a question about it

    Simply a question about it

    Hello,

    this package is incredibly good 🥇

    But, i am new to Dart, Flutter, animations and i have to invest much time to learn it.

    With one widget, Animator, you can do all the available animation in Flutter.

    Is that true, or morely just said because it sounds nice as description? I want to use flutter because of it's powerfull animations. Animator looks promising to me, so is it worth learning it first or is there much stuff which is not possible at all?

    Thank you 👍

    opened by n8crwlr 4
  • Reset Animator state?

    Reset Animator state?

    Is there a way to reset Animator state? Otherwise it works only for the first time it's created and can't trigger the new animation later on. Or am I missing something?

    opened by MihaMarkic 4
  • animator and sates rebuilder version problem?

    animator and sates rebuilder version problem?

    I get the following message when I try to use them together...

    Running "flutter pub get" in slider_tester...
    Because animator >=2.0.0 depends on states_rebuilder ^1.15.0 and slider_tester depends on states_rebuilder ^2.0.0, animator >=2.0.0 is forbidden.

    So, because slider_tester depends on animator ^2.0.0, version solving failed. pub get failed (1; So, because slider_tester depends on animator ^2.0.0, version solving failed.)

    Is this to be expected?

    greetings

    opened by jmwatte 3
  • Animator with latest states_rebuilder

    Animator with latest states_rebuilder

    can you update the example with latest states rebuilder?

    I am lost. I just want to show and hide an appBar, in debug console it says the animation started but the ui not animatin

    import 'package:animator/animator.dart';
    import 'package:flutter/material.dart';
    import 'package:states_rebuilder/states_rebuilder.dart';
    class ReaderService extends StatesRebuilderWithAnimator {
      bool showMenuBar = false;
      init(TickerProvider ticker) {
        animator.tweenMap = {
          "appBarAnim": Tween<double>(
            begin: showMenuBar ? -1 : 0,
            end: showMenuBar ? 0 : -1,
          ),
        };
        initAnimation(ticker);
        addAnimationListener(() {
          rebuildStates(["appBar"]);
        });
        animator.cycles = 1;
        animator.duration = Duration(milliseconds: 200);
    
        endAnimationListener(() => print("animation finished"));
      }
    
      startAnimation([bool reset = false]) {
        triggerAnimation(reset: reset);
      }
    
      dispose() {}
    }
    
    class ReaderTest extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Injector(
          inject: [Inject(() => ReaderService())],
          builder: (context) {
            var model = Injector.get<ReaderService>();
            return StateWithMixinBuilder(
              mixinWith: MixinWith.tickerProviderStateMixin,
              models: [model],
              initState: (ctx, ticker) => model.init(ticker),
              dispose: (_, ___) => model.dispose(),
              builder: (_, __) => Scaffold(
                body: Stack(
                  children: <Widget>[
                    Container(
                      child: GestureDetector(
                        onTap: () {
                          model.showMenuBar = !model.showMenuBar;
                          model.rebuildStates(["appBar"]);
    
                          model.startAnimation(true);
                        },
                      ),
                    ),
                    StateBuilder(
                        tag: "appBar",
                        models: [model],
                        builder: (_, __) {
                          return Align(
                              alignment: Alignment.topCenter,
                              child: FractionalTranslation(
                                translation: Offset(
                                    0, model.animationMap["appBarAnim"].value),
                                child: Container(
                                    height: 100,
                                    width: double.infinity,
                                    color: Colors.red,
                                    child: Center(
                                        child: Text("${model.showMenuBar}"))),
                              ));
                        }),
                  ],
                ),
              ),
            );
          },
        );
      }
    }
    
    
    
    opened by karnadii 3
  • Warning with Flutter 3.0.0

    Warning with Flutter 3.0.0

    Hello Sir! There is an issue when I try to run my old project after migrate it on flutter version 3.0.0, it seams that the warning come from animator.

    has type 'widgetsbinding' which excludes null. - 'widgetsbinding' some thing like that. Please check it.

    I apologize for not having introduced the related code and error

    opened by leenorshn 0
  • [New Feature] Staggered Animation using AnimateWidget

    [New Feature] Staggered Animation using AnimateWidget

    Staggered Animation

    Using AnimateWidget, you can specify for each animate value, its onw curve and reverseCurve using setCurve and setReverseCurve.

    This is the same example as in Flutter docs for staggered animation:

    class _MyStaggeredWidgetState extends State<MyStatefulWidget> {
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTap: () {
            setState(() {});
          },
          child: AnimateWidget(
            duration: const Duration(milliseconds: 2000),
            cycles: 2,
            triggerOnRebuild: true,
            triggerOnInit: false,
            builder: (context, animate) {
              final padding = animate
                  .setCurve(Interval(0.250, 0.375, curve: Curves.ease))
                  .fromTween(
                    (_) => EdgeInsetsTween(
                      begin: const EdgeInsets.only(bottom: 16.0),
                      end: const EdgeInsets.only(bottom: 75.0),
                    ),
                  );
              final opacity = animate
                  .setCurve(Interval(0.0, 0.100, curve: Curves.ease))
                  .fromTween(
                    (_) => Tween<double>(begin: 0.0, end: 1.0),
                  )!;
              final containerWidget = animate
                  .setCurve(Interval(0.125, 0.250, curve: Curves.ease))
                  .fromTween(
                    (_) => Tween<double>(begin: 50.0, end: 150.0),
                    'width',
                  )!;
              final containerHeight = animate
                  .setCurve(Interval(0.250, 0.375, curve: Curves.ease))
                  .fromTween(
                    (_) => Tween<double>(begin: 50.0, end: 150.0),
                    'height',
                  )!;
              final color = animate
                  .setCurve(Interval(0.500, 0.750, curve: Curves.ease))
                  .fromTween(
                    (_) => ColorTween(
                      begin: Colors.indigo[100],
                      end: Colors.orange[400],
                    ),
                  );
              final borderRadius = animate
                  .setCurve(Interval(0.375, 0.500, curve: Curves.ease))
                  .fromTween(
                    (_) => BorderRadiusTween(
                      begin: BorderRadius.circular(4.0),
                      end: BorderRadius.circular(75.0),
                    ),
                  );
              return Center(
                child: Container(
                  width: 300.0,
                  height: 300.0,
                  decoration: BoxDecoration(
                    color: Colors.black.withOpacity(0.1),
                    border: Border.all(
                      color: Colors.black.withOpacity(0.5),
                    ),
                  ),
                  child: Container(
                    padding: padding,
                    alignment: Alignment.bottomCenter,
                    child: Opacity(
                      opacity: opacity,
                      child: Container(
                        width: containerWidget,
                        height: containerHeight,
                        decoration: BoxDecoration(
                          color: color,
                          border: Border.all(
                            color: Colors.indigo[300]!,
                            width: 3.0,
                          ),
                          borderRadius: borderRadius,
                        ),
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        );
      }
    }
    

    Here is the full working example.

    One of the particularities of Animator is that you can use staggered animation with implicitly animated widget. Here is the above example with implicit staggered animation

    opened by GIfatahTH 0
  • [New Feature] AnimateWidge for implicit without the limitation of built-in Flutter widget for implicit animation

    [New Feature] AnimateWidge for implicit without the limitation of built-in Flutter widget for implicit animation

    I added a new widget called AnimateWidget that allows for implicit without limitation.

    Let's reproduce the AnimatedContainer example in official Flutter docs. (link here).

    In Flutter AnimatedContainer example, we see:

    Center(
        child: AnimatedContainer(
            duration: const Duration(seconds: 2),
            curve: Curves.fastOutSlowIn,
            width: selected ? 200.0 : 100.0,
            height: selected ? 100.0 : 200.0,
            color: selected ? Colors.red : Colors.blue,
            alignment: selected ? Alignment.center : AlignmentDirectional.topCenter,
            child: const FlutterLogo(size: 75),
        ),
    ),
    

    With animateWidget, we simply use theContainer` widget :

    Center(
        child: AnimatedWidget(
            duration: const Duration(seconds: 2),
            curve: Curves.fastOutSlowIn,
            (context, animate) => Container(
                // Animate is a callable class
                width: animate.call(selected ? 200.0 : 100.0),
                height: animate(selected ? 100.0 : 200.0, 'height'),
                color: animate(selected ? Colors.red : Colors.blue),
                alignment: animate(selected ? Alignment.center : AlignmentDirectional.topCenter),
                child: const FlutterLogo(size: 75),
            ),
        );
    ),
    
    • Using the exposed animate function, we set the animation start and end values.
    • As the width and height are the same type (double), we need to add a name to distinguish them.

    You can implicitly animate any type. Here we implicitly animated a double, Color, and Alignment values. If you want to animate two parameters of the same type, you just add a dummy name to distinguish them.

    That's all, you are not limited to use a widget that starts with Animated prefix to use implicit animation.

    Here is the full working example.

    opened by GIfatahTH 2
  • Animator should also support implicit animations.

    Animator should also support implicit animations.

    I am using an animated container to transform the position of the widget. Animated Container only requires one X and one Y point to do a transformation from one coordinate to another but I can't find any way to do that with the animator as I can't get the old X and Y.

    opened by itssidhere 1
Owner
MELLATI Fatah
MELLATI Fatah
In this repo you can expertise how to build various User Interface in Flutter

?? Flutter UI ?? Introduction The language used here is Dart, which is a object oriented programming language with the sdk called Flutter,It's a googl

navee-ramesh 17 Nov 5, 2022
Flutter animation tutorials, such common animation, flare animation.

❤️ Star ❤️ the repo to support the project or ?? Follow Me.Thanks! Facebook Page Facebook Group QQ Group Developer Flutter Open Flutter Open 963828159

Flutter开源社区 123 Sep 3, 2022
Flutter animation tutorials, such common animation, flare animation.

❤️ Star ❤️ the repo to support the project or ?? Follow Me.Thanks! Facebook Page Facebook Group QQ Group Developer Flutter Open Flutter Open 963828159

Flutter开源社区 123 Sep 3, 2022
Sample Flutter Drawing App which allows the user to draw onto the canvas along with color picker and brush thickness slider.

DrawApp Sample Flutter Drawing App which allows the user to draw onto the canvas along with color picker and brush thickness slider. All code free to

Jake Gough 226 Nov 3, 2022
A draggable Flutter widget that makes implementing a SlidingUpPanel much easier!

sliding_up_panel A draggable Flutter widget that makes implementing a SlidingUpPanel much easier! Based on the Material Design bottom sheet component,

Akshath Jain 1.2k Nov 26, 2022
A flutter package which makes it easier to display the difference between two images.

?? Before After A flutter package which makes it easier to display the differences between two images.. The source code is 100% Dart, and everything r

Sahil Kumar 726 Nov 22, 2022
A custom Flutter value slider that makes a wave effect when dragged.

A Flutter slider that makes a wave effect when dragged. Does a little bounce when dropped. Demo Getting Started To use this plugin, add wave_slider as

Gordon Hayes 35 Sep 27, 2022
Flutter Login interface using basic widgets such as Row, Column

Login UI - Flutter Descrição do Projeto ?? Interface de login utilizando widgets

null 2 Oct 25, 2022
A simple animated circular menu for Flutter, Adjustable radius, colors, alignment, animation curve and animation duration.

A simple animated circular menu for Flutter, Adjustable radius, colors, alignment, animation curve and animation duration. pub package Getting Started

Hasan Mohammed 90 Nov 21, 2022
BKash-Ballance-Animation - BKash Ballance Animation For Flutter

BKash-Ballance-Animation before clone the GitHub repository please give a star o

Blackshadow Software Ltd 11 Sep 1, 2022
Fisherman-Fishing-Animation - Fisherman Fishing Animation With Flutter

Fisherman Fishing Animation before clone the GitHub repository please give a sta

Blackshadow Software Ltd 9 Oct 27, 2022
Nubank card animation - Nubank card animation built with flutter

Nubank card animation Project | Technologies | How to run | How to contribute ??

Lucas da Silva Barbosa 8 Nov 6, 2022
Fade animation - Add fade animation to your app easily

fade_animation Add fade animation to your app easily using simple_animations pac

Mazouzi Aymene 3 Oct 6, 2022
A Flutter library for gradually painting SVG path objects on canvas (drawing line animation).

drawing_animation From static SVG assets See more examples in the showcasing app. Dynamically created from Path objects which are animated over time m

null 435 Oct 25, 2022
A flutter package which display the library collapse according to the number of images associated with hero animation

?? Gallery Collapse A flutter package which display the library collapse accordi

null 6 Sep 12, 2022
A library for handling animation warmup generically

This solution is not very scalable for applications with many animations to warm up and is meant mostly as an example of an approach applications could take to warmup their animations until a more permanent solution is available.

Dan Reynolds 41 Oct 20, 2022
A Flutter package allows you to Showcase/Highlight your widgets step by step.

ShowCaseView A Flutter package allows you to Showcase/Highlight your widgets step by step. Preview Installing Add dependency to pubspec.yaml Get the l

kirill 6 Nov 12, 2022
A collection of Animations that aims to improve the user experience for your next flutter project.

A collection of Animations that aims to improve the user experience for your next flutter project.

Ezaldeen Sahb 132 Sep 13, 2022
A widget that allow user resize the widget with drag

Flutter-Resizable-Widget A widget that allow user resize the widget with drag Note: this widget uses Getx Example bandicam.2021-11-11.12-34-41-056.mp4

MohammadAminZamani.afshar 20 Sep 4, 2022