MaterialPageRoute:从入门到精通
路由导航这件事,说白了就是页面之间的跳转。在Flutter里,MaterialPageRoute是最常用的路由方式。我个人习惯把它当作「默认选项」——除非有特殊需求,否则用它准没错。
基本用法:三行代码搞定跳转
先看一个最简单的例子。从首页跳转到详情页,代码长这样:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(),
),
);
嗯,就这么简单。builder参数返回你要跳转的目标页面。返回上一页用Navigator.pop(context)。
我在项目中遇到过一个问题:新手容易忘记context必须是当前页面的上下文。如果你在异步回调里用Navigator.push,记得先检查context是否还活着。
DetailPage(id: 123)。
页面过渡动画:默认的就很香
MaterialPageRoute自带Material Design风格的过渡动画。Android上是从底部滑入,iOS上是从右侧滑入。你想想看,这其实挺合理的——平台一致性嘛。
但有时候默认动画不太够用。比如我做电商项目时,产品详情页需要从底部弹出,像抽屉一样。这时候就要动点手脚了。
自定义过渡效果:让页面动起来
自定义过渡的核心是重写buildTransitions方法。来看一个从底部滑入的例子:
class BottomSlideRoute extends PageRouteBuilder {
final Widget page;
BottomSlideRoute({required this.page})
: super(
pageBuilder: (context, animation, secondaryAnimation) => page,
transitionsBuilder: (context, animation, secondaryAnimation, child) {
const begin = Offset(0.0, 1.0);
const end = Offset.zero;
const curve = Curves.easeInOut;
var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
var offsetAnimation = animation.drive(tween);
return SlideTransition(
position: offsetAnimation,
child: child,
);
},
);
}
这里的关键是transitionsBuilder。它接收四个参数:
context:构建上下文animation:主动画,值从0到1secondaryAnimation:副动画,用于处理返回时的效果child:目标页面组件
你可以在animation上做各种变换。缩放、旋转、透明度,随便玩。
避坑指南:我曾经踩过的坑
我曾经在自定义过渡动画时,忘记处理secondaryAnimation。结果页面返回时动画卡顿,用户体验很差。后来我加上了secondaryAnimation的监听,问题才解决。
还有一个坑:PageRouteBuilder的transitionDuration默认是300毫秒。如果你觉得太快或太慢,可以手动设置:
return MaterialPageRoute(
transitionDuration: Duration(milliseconds: 500),
builder: (context) => DetailPage(),
);
进阶:组合动画效果
有时候单一动画不够炫酷。比如我想让页面从底部滑入的同时,透明度也从0变到1。组合动画用AnimationController的drive方法:
transitionsBuilder: (context, animation, secondaryAnimation, child) {
var slideTween = Tween<Offset>(
begin: Offset(0.0, 1.0),
end: Offset.zero,
);
var fadeTween = Tween<double>(
begin: 0.0,
end: 1.0,
);
var slideAnimation = slideTween.animate(animation);
var fadeAnimation = fadeTween.animate(animation);
return SlideTransition(
position: slideAnimation,
child: FadeTransition(
opacity: fadeAnimation,
child: child,
),
);
},
你看,把SlideTransition和FadeTransition嵌套起来就行。外层控制位置,内层控制透明度。
性能优化:别让动画卡顿
自定义动画时,记得用const构造函数。我在项目中遇到过动画掉帧的问题,排查后发现是页面组件没有用const。加上之后,动画流畅多了。
| 优化点 | 说明 |
|---|---|
| 使用const构造函数 | 减少重建次数 |
| 避免复杂计算 | 动画帧率60fps,计算要快 |
| 使用RepaintBoundary | 隔离重绘区域 |
setState在频繁触发。动画期间尽量减少状态更新。
总结一下
MaterialPageRoute是Flutter路由的基石。默认动画够用,自定义也不难。你想想看,掌握了这些,大部分页面跳转场景都能搞定。
最后提醒一句:动画是为了提升体验,不是为了炫技。我见过有人把页面跳转做成3D翻转,结果用户晕头转向。嗯,适可而止就好。