[Flutter actual combat] animation sequence, sharing animation, routing animation

Lao Meng's guide: This article is the fourth in the Flutter animation series. This article introduces animation sequences, sharing animations, and routing animations.

Animation sequence

The combined animation is used in Flutter Interval, Intervalinherited from it Curve, and the usage is as follows:

Animation _sizeAnimation = Tween(begin: 100.0, end: 300.0).animate(CurvedAnimation(
    parent: _animationController, curve: Interval(0.5, 1.0)));

Indicates that the _sizeAnimationanimation starts from 0.5 (half) to the end. If the animation duration is 6 seconds, _sizeAnimationit starts from the third second.

IntervalIn beginand endthe SP value is 0.0 to 1.0.

The following is to implement a color change first and then a size change. The code is as follows:

class AnimationDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _AnimationDemo();
}

class _AnimationDemo extends State<AnimationDemo>
    with SingleTickerProviderStateMixin {
  AnimationController _animationController;
  Animation _colorAnimation;
  Animation _sizeAnimation;

  @override
  void initState() {
    _animationController =
        AnimationController(duration: Duration(seconds: 5), vsync: this)
    ..addListener((){setState(() {

    });});

    _colorAnimation = ColorTween(begin: Colors.red, end: Colors.blue).animate(
        CurvedAnimation(
            parent: _animationController, curve: Interval(0.0, 0.5)));

    _sizeAnimation = Tween(begin: 100.0, end: 300.0).animate(CurvedAnimation(
        parent: _animationController, curve: Interval(0.5, 1.0)));

    //开始动画
    _animationController.forward();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Container(
              height: _sizeAnimation.value,
              width: _sizeAnimation.value,
              color: _colorAnimation.value),
        ],
      ),
    );
  }

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

The effect is as follows:

We can also set up simultaneous animation, just change Intervalthe values ​​of both Interval(0.0, 1.0).

Imagine the following scene, a red box, the animation duration is 6 seconds, the first 40% of the time is from 100->200, then 200 is unchanged for 20% of the time, and the last 40% of the time is from 200->300. This effect is achieved by TweenSequence, the code is as follows:

_animation = TweenSequence([
  TweenSequenceItem(
      tween: Tween(begin: 100.0, end: 200.0)
          .chain(CurveTween(curve: Curves.easeIn)),
      weight: 40),
  TweenSequenceItem(tween: ConstantTween<double>(200.0), weight: 20),
  TweenSequenceItem(tween: Tween(begin: 200.0, end: 300.0), weight: 40),
]).animate(_animationController);

weightIndicates the weight of each Tween.

The final effect is as follows:

Share animation

Hero is our commonly used transition animation. When the user clicks on a picture and switches to another page, this page also has this picture. Then it is appropriate to use the Hero component. Let’s take a look at the rendering of Hero:

The code of the list page achieved by the above effect is as follows:

class HeroDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _HeroDemo();
}

class _HeroDemo extends State<HeroDemo> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GridView(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3, crossAxisSpacing: 5, mainAxisSpacing: 3),
        children: List.generate(10, (index) {
          if (index == 6) {
            return InkWell(
              onTap: () {
                Navigator.push(
                    context,
                    new MaterialPageRoute(
                        builder: (context) => new _Hero1Demo()));
              },
              child: Hero(
                tag: 'hero',
                child: Container(
                  child: Image.asset(
                    'images/bird.png',
                    fit: BoxFit.fitWidth,
                  ),
                ),
              ),
            );
          }
          return Container(
            color: Colors.red,
          );
        }),
      ),
    );
  }
}

The second page code is as follows:

class _Hero1Demo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
          alignment: Alignment.topCenter,
          child: Hero(
            tag: 'hero',
            child: Container(
              child: Image.asset(
                'images/bird.png',
              ),
            ),
          )),
    );
  }
}

Both pages have Hero controls, and the tagparameters are the same.

Routing animation

Transition is to jump from the current page to another page. The jump page is jumped to the new page through the Navigator in Flutter as follows:

Navigator.push(context, MaterialPageRoute(builder: (context) {
  return _TwoPage();
}));

Go back to the previous page:

Navigator.pop(context);

Flutter provides two transition animations, namely MaterialPageRoute and CupertinoPageRoute . MaterialPageRoute displays different effects according to different platforms. The Android effect is from bottom to top, and the iOS effect is from left to right. CupertinoPageRoute is from left to right regardless of platform.

Examples of using MaterialPageRoute are as follows:

class NavigationAnimation extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: OutlineButton(
          child: Text('跳转'),
          onPressed: () {
            Navigator.push(context, CupertinoPageRoute(builder: (context) {
              return _TwoPage();
            }));
          },
        ),
      ),
    );
  }
}

class _TwoPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        color: Colors.blue,
      ),
    );
  }
}

iOS effect:

What if I want to customize the transition animation?

Customizing any component is the same. If the system is similar, just look at how the source code is implemented, and then customize the component according to its template.

Back to the topic, look at the inheritance relationship of MaterialPageRoute:

PageRoute's inheritance relationship:

MaterialPageRoute and CupertinoPageRoute both inherit from PageRoute, so the focus is on PageRoute. PageRoute is an abstract class, and its subclass also has a PageRouteBuilder. By looking at its name, you know that this is a custom animation effect. PageRouteBuilder source code:

pageBuilder Indicates the page to jump to.

transitionsBuilder Indicates the animation effect of the page, the default value code:

Widget _defaultTransitionsBuilder(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
  return child;
}

Found through the source code, there is no animation effect by default.

The custom transition animation only needs to transitionsBuilderbe modified :

Navigator.push(
    context,
    PageRouteBuilder(pageBuilder: (
      BuildContext context,
      Animation<double> animation,
      Animation<double> secondaryAnimation,
    ) {
      return _TwoPage();
    }, transitionsBuilder: (BuildContext context,
        Animation<double> animation,
        Animation<double> secondaryAnimation,
        Widget child) {
      return SlideTransition(
        position: Tween(begin: Offset(-1, 0), end: Offset(0, 0))
            .animate(animation),
        child: child,
      );
    }));

Encapsulate it for easy use:

class LeftToRightPageRoute extends PageRouteBuilder {
  final Widget newPage;

  LeftToRightPageRoute(this.newPage)
      : super(
          pageBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
          ) =>
              newPage,
          transitionsBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
            Widget child,
          ) =>
              SlideTransition(
            position: Tween(begin: Offset(-1, 0), end: Offset(0, 0))
                .animate(animation),
            child: child,
          ),
        );
}

use:

Navigator.push(context, LeftToRightPageRoute(_TwoPage()));

Not only these panning paintings, but also the animations such as rotation and zooming that you learned before can directly replace SlideTransition.

The above animation only animates the new page. If you want to achieve the effect of the current page being ejected from the top by the new page, the implementation is as follows:

class CustomPageRoute extends PageRouteBuilder {
  final Widget currentPage;
  final Widget newPage;

  CustomPageRoute(this.currentPage, this.newPage)
      : super(
          pageBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
          ) =>
              currentPage,
          transitionsBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
            Widget child,
          ) =>
              Stack(
            children: <Widget>[
              SlideTransition(
                position: new Tween<Offset>(
                  begin: const Offset(0, 0),
                  end: const Offset(0, -1),
                ).animate(animation),
                child: currentPage,
              ),
              SlideTransition(
                position: new Tween<Offset>(
                  begin: const Offset(0, 1),
                  end: Offset(0, 0),
                ).animate(animation),
                child: newPage,
              )
            ],
          ),
        );
}

The essence is to animate two pages, using:

Navigator.push(context, CustomPageRoute(this, _TwoPage()));

In addition to custom routing animations, at the Flutter 1.17 release conference, the Flutter team also released a new Animations package, which provides pre-built animations that implement the new Material motion specifications.

It provides a series of animations, some effects:

Details: https://juejin.im/post/6847902223909781511

communicate with

Laomeng Flutter blog address (330 control usage): http://laomengit.com

Welcome to join the Flutter exchange group (WeChat: laomengit) and follow the public account [Lao Meng Flutter]:

Guess you like

Origin blog.csdn.net/mengks1987/article/details/108212636