Flutter Development Diary: Detailed Explanation of Flutter Animation Positioned Transition

Keywords: Attribute

This article has authorized the exclusive publication and reproducing of the Wechat Public Number Y YYGeeker. Please indicate the source.

Control introduction

  1. Positioned Transition represents an animation of a rectangular position, which can be controlled by the controller to change the rectangular value of the animation, thereby controlling the rectangular position of the animation.

Constructor

PositionedTransition({
    Key key,
    this.rect,                       //Change of rectangular position value in animation
    Widget child,                    //Animation sub-elements
})

Usage method

1. Packaging animation

We can wrap common attributes as a control

  • child: Represents elements passed in from outside, wrapped by Positioned Transition
  • rect: Represents the change in the value of the animation attribute passed in from outside, and fills it in the rectangular position of the child by obtaining its value.

Note here that the parent control of PositionedTransition must be Stack

class AnimatorTransition extends StatelessWidget {
  final Widget child;
  final Animation<RelativeRect> animation;

  AnimatorTransition({this.child, this.animation});

  @override
  Widget build(BuildContext context) {
    //The animation of absolute positioning needs Stack package
    return Stack(
      children: <Widget>[
        PositionedTransition(
          rect: animation,
          child: this.child,
        ),
      ],
    );
  }
}

2. Control animation

  • Animation Controller is needed to control the change of animation attribute values.
  • Setting up its interpolator through Curved Animation
  • Set the range of its value by Relative RectTween
class WeWidgetState extends State<WeWidget>
    with SingleTickerProviderStateMixin {
    
  Animation<RelativeRect> _animation;
  AnimationController _controller;
  Animation _curve;

  @override
  void initState() {
    super.initState();

    //Animation Controller
    _controller = AnimationController(
      duration: const Duration(milliseconds: 3000),
      vsync: this,
    );
    //Animation Interpolator
    _curve = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn);
    //Range of animation change
    _animation = RelativeRectTween(
            begin: RelativeRect.fromLTRB(200.0, 200.0, 200.0, 200.0),
            end: RelativeRect.fromLTRB(20.0, 20.0, 20.0, 20.0))
        .animate(_curve);
    //Start animation
    _controller.forward();
  }
}

3. Monitoring animation

  • Monitor changes in animation status by addStatusListener and changes in animation value by addListener
class WeWidgetState extends State<WeWidget>
    with SingleTickerProviderStateMixin {
  Animation<RelativeRect> _animation;
  AnimationController _controller;
  Animation _curve;

  double _animationValue;
  AnimationStatus _state;

  @override
  void initState() {
    super.initState();

    //Animation Controller
    _controller = AnimationController(
      duration: const Duration(milliseconds: 3000),
      vsync: this,
    );
    //Animation Interpolator
    _curve = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn);
    //Range of animation change
    _animation = RelativeRectTween(
            begin: RelativeRect.fromLTRB(200.0, 200.0, 200.0, 200.0),
            end: RelativeRect.fromLTRB(20.0, 20.0, 20.0, 20.0))
      .animate(_curve)
      ..addListener(() {
        setState(() {
          //Record changes in values
          _animationValue = _animation.value;
        });
      })
      ..addStatusListener((AnimationStatus state) {
        //If the animation is finished, reverse the drawing.
        if (state == AnimationStatus.completed) {
          _controller.reverse();
        } else if (state == AnimationStatus.dismissed) {
        //If the animation has disappeared, start animation
          _controller.forward();
        }

        setState(() {
          _state = state;
        });
      });
    //Start animation
    _controller.forward();
  }
}

Design sketch

source code

import 'package:flutter/material.dart';

class Day13 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primaryColor: Colors.white,
      ),
      home: WeWidget(),
    );
  }
}

class WeWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return WeWidgetState();
  }
}

class WeWidgetState extends State<WeWidget>
    with SingleTickerProviderStateMixin {
  Animation<RelativeRect> _animation;
  AnimationController _controller;
  Animation _curve;

  RelativeRect _animationValue;
  AnimationStatus _state;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      duration: const Duration(milliseconds: 3000),
      vsync: this,
    );
    _curve = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn);
    _animation = RelativeRectTween(
            begin: RelativeRect.fromLTRB(200.0, 200.0, 200.0, 200.0),
            end: RelativeRect.fromLTRB(20.0, 20.0, 20.0, 20.0))
        .animate(_curve)
          ..addListener(() {
            setState(() {
              _animationValue = _animation.value;
            });
          })
          ..addStatusListener((AnimationStatus state) {
            if (state == AnimationStatus.completed) {
              _controller.reverse();
            } else if (state == AnimationStatus.dismissed) {
              _controller.forward();
            }

            setState(() {
              _state = state;
            });
          });
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("day13"),
      ),
      body: _buildColumn(),
    );
  }

  Widget _buildColumn() {
    return Stack(
      children: <Widget>[
        AnimatorTransition(
          child: FlutterLogo(
            style: FlutterLogoStyle.horizontal,
            size: 200,
          ),
          animation: _animation,
        ),
        Padding(
          padding: EdgeInsets.fromLTRB(0, 15, 0, 0),
          child: Text("Animation value:" + _animationValue.toString()),
        ),
        Padding(
          padding: EdgeInsets.fromLTRB(0, 30, 0, 0),
          child: Text("Animation status:" + _state.toString()),
        ),
      ],
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

class AnimatorTransition extends StatelessWidget {
  final Widget child;
  final Animation<RelativeRect> animation;

  AnimatorTransition({this.child, this.animation});

  @override
  Widget build(BuildContext context) {
    //The animation of absolute positioning needs Stack package
    return Stack(
      children: <Widget>[
        PositionedTransition(
          rect: animation,
          child: this.child,
        ),
      ],
    );
  }
}

Posted by west4me on Sat, 12 Oct 2019 14:32:41 -0700