2019-11-11 Flutter 页面如何跳转?
Flutter 页面如何跳转?
一、Navigator介绍
Navigator 继承自 StatefulWidget,它也是小组件,它有很多相关静态函数,可以帮我们达到页面跳转和数据交互的功能:
-
push 将设置的router信息推送到Navigator上,实现页面跳转。
-
of 主要是获取Navigator最近的Widget。
-
pop 导航到新页面,或者返回到上个页面。
-
canPop 判断是否可以导航到新页面
-
maybePop 可能会导航到新页面
-
popAndPushNamed 指定一个路由路径,并导航到新页面。
-
popUntil 反复执行pop 直到该函数的参数predicate返回true为止。
-
pushAndRemoveUntil 将给定路由推送到Navigator,删除先前的路由,直到该函数的参数predicate返回true为止。
-
pushNamedAndRemoveUntil 将命名路由推送到Navigator,删除先前的路由,直到该函数的参数predicate返回true为止。
-
pushNamed 将命名路由推送到Navigator。
-
pushReplacement 路由替换。
-
pushReplacementNamed 替换路由操作。推送一个命名路由到Navigator,新路由完成动画之后处理上一个路由。
-
removeRoute 从Navigator中删除路由,同时执行Route.dispose操作。
-
removeRouteBelow 从Navigator中删除路由,同时执行Route.dispose操作,要替换的路由是传入参数anchorRouter里面的路由。
-
replace 将Navigator中的路由替换成一个新路由。
-
replaceRouteBelow 将Navigator中的路由替换成一个新路由,要替换的路由是是传入参数anchorRouter里面的路由。
二、Navigator使用
2.1 push && pop
- 代码
//跳转下一页
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondPage())
);
context: 上下文
MaterialPageRoute: 必须要传入一个闭包函数 WidgetBuilder,该闭包函数的参数是 BuildContext对象.
//返回上一页
Navigator.pop(context);
2.2 pushNamed
- 代码
Navigator.of(context).pushNamed('/page2');
此种方法只是简单的将我们需要进入的页面push到栈顶,以此来显示当前页面,
其参数是一个字符串类型,传入的是页面对应的路由名称
该路由名称需要在程序主入口中进行定义。定义方法为:
void main() {
runApp(
new MaterialApp(
home: new Page1(),
routes: <String, WidgetBuilder> {
'/page1': (BuildContext context) => new Page1(),
'/page2' : (BuildContext context) => new Page2(),
'/page3' : (BuildContext context) => new Page3(),
},
)
);
}
使用:Navigator.of(context).pushNamed('/page1');
直接进入screen1页面(每次都将新建一个新的页面)
2.2 pushReplacementNamed && pushReplacement
- 代码
Navigator.of(context).pushReplacementNamed('/page3');
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => Page3()));
指把当前页面在栈中的位置替换成跳转的页面(替换导航器的当前路由,通过推送路由[routeName]),当新的页面进入后,之前的页面将执行dispose方法。
即比如当前从页面1进入页面2,在页面2使用 pushReplacementNamed 进入页面3,当进入了页面3后,页面2将执行dispose方法,此时在页面3返回时,会回到页面1.
使用场景:
例如从SplashScreen到HomeScreen。它应该只显示一次,用户不应该再从主屏幕回到它。在这种情况下,由于我们将要进入一个全新的屏幕,
我们可能想要使用这个方法来实现它的enter animation属性。
2.2 popAndPushNamed
- 代码
Navigator.popAndPushNamed(context, '/page3');
Navigator.of(context).popAndPushNamed('/page3');
指将当前页面pop,然后跳转到指定页面(将当前路由弹出导航器,并将命名路由推到它的位置。)
使用场景:
例如在购物应用中,有产品列表,用户在产品列表中可以通过筛选,来进一步选择商品,在这个过程中,用户点击筛选按钮时,会进入筛选条件选择界面,当用户点击
确定筛选按钮时,应pop掉筛选界面,并使用新的筛选条件进入产品列表。这种情况popAndPushNamed就比较合适了。
2.3 pushNamedAndRemoveUntil && pushAndRemoveUntil
-
方式一
Navigator.of(context).pushNamedAndRemoveUntil( '/page3', (Route<dynamic> route) => false );
Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (context) => Page4()), (Route<dynamic> route) => false, );
指将指定的页面 page3 加入到路由中,然后将其他所有的页面全部pop, (Route<dynamic> route) => false 将确保删除推送路线之前的所有路线。
这时候将打开一个新的 page3 页面, 实际上就是将新的Page3 重新设置成了根(root)
使用场景:
例如当用户点击了退出登录时,我们需要进入某一个页面(比如点退出登录后进入了登录页),这个时候用户点击返回时不应该能进入任何一个页面,这种情况就可以使用。
-
方式二
Navigator.of(context).pushNamedAndRemoveUntil( '/page4', ModalRoute.withName('/page1') );
缺点是必须page1有被注册过 Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (context) => Page4()), ModalRoute.withName('/page1'), );
指将指定的页面加入到路由中,然后将之前的路径移除知道指定的页面为止(将具有给定名称的路由推到导航器上,然后删除所有路径前面的路由直到'predicate'返回true为止。)即会移除掉 /page1 和 /page4 之间的所有页面。
使用场景:
例如一个购物应用程序的例子!或者任何需要支付交易的应用程序。因此,在这些应用程序中,一旦用户完成了支付事件,所有与交易或购物车相关的屏幕都应该从堆栈中删除,用户应该进入到支付确认页面。单击back按钮应将它们返回到产品列表或主屏幕。
使用实例:
1-->2-->3,3到4时使用Navigator.pushNamedAndRemoveUntil(context,"/page4",ModalRoute.withName('/page1'));
这时候如果在页面4点击返回,将会返回到1。
1-->2-->3,3到4时使用Navigator.pushNamedAndRemoveUntil(context,"/page4",ModalRoute.withName('/'));
这时候如果在页面4点击返回,将会直接回到root页面。
1-->2-->1-->2-->3,3到4时使用Navigator.pushNamedAndRemoveUntil(context,"/page4",ModalRoute.withName('/page1'));
这时候如果在页面4点击返回,将会回到第二个1页面。
2.3 popUntil
- 代码
Navigator.popUntil(context, ModalRoute.withName('/page2'));
使用场景:
有些应用场景下,用户可能不得不填写一个由三部分组成的长表单,该表单可能在移动应用程序的三个连续屏幕中显示。现在在表单的第三个页面,用户决定取消填写表单。用户单击Cancel,就会弹出所有之前的与表单相关的屏幕,并将用户带回主屏幕,从而丢失所有与表单相关的数据(在这种情况下,这是我们想要的)。我们不会在这里推出任何新东西,只是回到以前的路线。
2.4 maybePop && canPop
- 代码
Navigator.of(context).maybePop();
maybePop 会自动进行判断,如果当前页面pop后,会显示其他页面,不会出现问题,则将执行当前页面的pop操作,否则将不执行。
Navigator.of(context).canPop();
canPop 判断当前页面能否进行pop操作,并返回bool值
Navigator.of(context).pop();
直接退出当前页面
三、页面参数传递
-
参数传递
传参的方式很简单,在需要接收参数的页面进行参数定义,并加入其构造函数中,在跳转到该页面时,使用MaterialPageRoute并在页面中传入参数即可。
String params;
Navigator.push(
context,
MaterialPageRoute(builder: (context) => TestPage(params))
);
接收参数
class TestPage extends StatelessWidget {
final String userName;
mainPage(this.userName);
@override
Widget build(BuildContext context) {
print(userName);
return Container();
}
}
带返回值的页面跳转:
String userName = "xxx";
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Page5(userName)))
.then((data){
result =data;
print(result);
}
);
class Page5 extends StatelessWidget {
final String userName;
Page5(this.userName);
@override
Widget build(BuildContext context) {
print(userName);
return Container(
child: RaisedButton(
child: Text('下一页'),
onPressed: (){
Navigator.of(context).pop('page5返回的参数');
},
);
}
然后 Page5 中,在返回时使用:Navigator.of(context).pop('params');
在pop中写上返回的的值,这时候在上方的then中即可得到返回的数据。