animator icon indicating copy to clipboard operation
animator copied to clipboard

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

Open GIfatahTH opened this issue 3 years ago • 2 comments

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 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.

GIfatahTH avatar Jun 09 '21 18:06 GIfatahTH

Explicit Animation

With AnimateWidget you can also do explict 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.

GIfatahTH avatar Jun 09 '21 18:06 GIfatahTH

Here is the full interface of AnimateWidget

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
      )
    

GIfatahTH avatar Jun 09 '21 18:06 GIfatahTH