这篇文章主要给大家介绍了关于如何利用Flutter实现“孔雀开屏”的动画效果,文中通过示例代码介绍的非常详细,对大家学习或者使用Flutter具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
前言
今天分享一个类似“孔雀开屏”的动画效果,打开新的页面时,新的页面从屏幕右上角以圆形逐渐打开到全屏。
先来看下具体的效果
不知道这种效果大家叫什么名字?如果有更合适的名字可以在评论处告诉我,下面来说下如何实现此效果。
在使用Navigator进入一个新的页面时,通常用法如下:
Navigator.of(context).push(MaterialPageRoute(
builder: (context){
return PageB();
}
));
MaterialPageRoute就包含了切换页面时的动画效果,在iOS上效果是左右滑动切换,在Android上效果是上下滑动,如果想要自定义切换效果如何实现呢?答案是使用PageRouteBuilder,用法如下:
Navigator.of(context).push(PageRouteBuilder(pageBuilder:
(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
...
}));
在pageBuilder函数中使用animation返回新页面的动画效果即可。
新的页面以圆形效果逐渐打开,注意并没有缩放效果,所以新的页面是被裁减的,新的页面以右上角为圆心,半径逐渐变大进行裁切,就是我们想要的效果。
通过上面的分析,使用ClipPath对新的页面进行裁切
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(),
);
}));
重点是CirclePath,这就是裁切的路径,
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;
}
}
由于Path没有直接添加圆形的API函数,因此使用椭圆方法,只需将椭圆的矩形区域设置为正方形,那么裁切出来的就是圆形。
半径的最大值并不是屏幕的宽或者高,而是屏幕的对角线长度。
由于是从右上角开始,而且裁切的矩形区域必须是正方形,所以裁切的矩形区域是超出页面区域的。
如果很多页面都用到了这个效果,可以进行封装,类似于MaterialPageRoute,封装如下:
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),
);
}
}
使用
Navigator.of(context).push(CirclePageRoute(builder: (context) {
return PageB();
}));
如果你查看CupertinoPageRoute、MaterialPageRoute、PageRouteBuilder的源码,你会发现这3个都是继承自PageRoute,所以,不知不觉我们又学会了自定义路由。
总结
到此这篇关于利用Flutter实现“孔雀开屏”的动画效果的文章就介绍到这了,更多相关Flutter动画效果内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!