Animation effect of "peacock opens screen" in Flutter

Guide reading for Lao Meng: today, I share an animation effect similar to "peacock opens the screen". When opening a new page, the new page will gradually open to the full screen from the top right corner of the screen.

Let's see the specific effect first

I don't know the name of this effect? If you have a more appropriate name, please let me know in the comments. Let's talk about how to achieve this effect.

When using Navigator to enter a new page, the general usage is as follows:

Navigator.of(context).push(MaterialPageRoute(
  builder: (context){
    return PageB();
  }
));

MaterialPageRoute includes the animation effect when switching pages. On iOS, the effect is sliding left and right. On Android, the effect is sliding up and down. How do you want to customize the switching effect? The answer is to use PageRouteBuilder as follows:

Navigator.of(context).push(PageRouteBuilder(pageBuilder:
    (BuildContext context, Animation<double> animation,
        Animation<double> secondaryAnimation) {
  ...
}));

In the pageBuilder function, use animation to return the animation effect of the new page.

The new page opens gradually with a circular effect. Note that there is no scaling effect, so the new page is cut. The new page takes the upper right corner as the center and the radius becomes larger gradually for cutting, which is the effect we want.

Through the above analysis, use ClipPath to cut the new page

Navigator.of(context).push(PageRouteBuilder(pageBuilder:
    (BuildContext context, Animation<double> animation,
        Animation<double> secondaryAnimation) {
  return AnimatedBuilder(
    animation: animation,
    builder: (context, child) {
      return ClipPath(
        clipper: CirclePath(animation.value),
        child: child,
      );
    },
    child: PageB(),
  );
}));

The key point is CirclePath, which is the cutting path,

class CirclePath extends CustomClipper<Path> {
  CirclePath(this.value);

  final double value;

  @override
  Path getClip(Size size) {
    var path = Path();
    double radius =
        value * sqrt(size.height * size.height + size.width * size.width);
    path.addOval(Rect.fromLTRB(
        size.width - radius, -radius, size.width + radius, radius));
    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) {
    return true;
  }
}

Because Path does not directly add the API function of circle, using the ellipse method, you only need to set the rectangle area of the ellipse as a square, and then the circle will be cut out.

The maximum radius is not the width or height of the screen, but the diagonal length of the screen.

Since it starts from the upper right corner, and the rectangular area to be cut must be square, the rectangular area to be cut is beyond the page area.

If this effect is used in many pages, it can be encapsulated, similar to MaterialPageRoute, as follows:

class CirclePageRoute extends PageRoute {
  CirclePageRoute({
    @required this.builder,
    this.transitionDuration = const Duration(milliseconds: 500),
    this.opaque = true,
    this.barrierDismissible = false,
    this.barrierColor,
    this.barrierLabel,
    this.maintainState = true,
  });

  final WidgetBuilder builder;

  @override
  final Duration transitionDuration;

  @override
  final bool opaque;

  @override
  final bool barrierDismissible;

  @override
  final Color barrierColor;

  @override
  final String barrierLabel;

  @override
  final bool maintainState;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation) {
    return AnimatedBuilder(
      animation: animation,
      builder: (context, child) {
        return ClipPath(
          clipper: CirclePath(animation.value),
          child: child,
        );
      },
      child: builder(context),
    );
  }
}

use

Navigator.of(context).push(CirclePageRoute(builder: (context) {
  return PageB();
}));

If you look at the source code of CupertinoPageRoute, MaterialPageRoute and PageRouteBuilder, you will find that these three are all inherited from PageRoute, so unconsciously we have learned to customize routes.

communication

Blog address of Lao Meng Flutter (nearly 200 controls usage): http://laomengit.com

Welcome to Flutter exchange group (WeChat: laomengit) and official account [Lao Meng Flutter]:

Tags: Mobile iOS Android

Posted on Sun, 24 May 2020 09:08:48 -0400 by geek_girl_2020