Navigator
Navigator是一个路由管理组件,他提供了打开和关闭页面的方法,同时打开关闭弹窗也是一样的原理
在flutter中打开一个页面可以使用简单粗暴的方法,即
Navigator.of(context).push(MaterialPageRoute(builder: (context){
return TsmScaffoldPage();
},settings: RouteSettings(arguments: 'value')));
此种打开方式可以直接打开任何页面,但是由于在实际开发过程中这么写比较零散,不推荐这么写,
打开命名路由
在MaterialApp();
MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
routes: {
page_routes_container: (context) => TsmContainerPage(),
page_routes_scaffold: (context) => TsmScaffoldPage(),
page_routes_appbar: (context) => TsmAppBarPage(),
page_routes_row_and_column: (context) => TsmRowAndColumnPage(),
page_routes_text: (context) => TsmTextPage(),
page_routes_text_field: (context) => TsmTextFieldPage(),
page_routes_raised_button: (context) => TsmRaisedButtonPage(),
page_routes_icon: (context) => TsmIconPage(),
page_routes_iamge: (context) => TsmImagePage(),
page_routes_single_child_scroll_view: (context) =>
TsmSingleChildScrollViewPage(),
page_routes_scroll_base: (context) => ScrollBasePage(),
page_routes_grid_view: (context) => TsmGridViewPage(),
page_routes_list_view: (context) => TsmListViewPage(),
},
home: TsmMainPage(),
);
首先需要在MaterialApp 的 routes 下面配置一个路径和widget的对应关系,
在这里你会发现这样的跳转比上面那个跳转清晰多了,
再来一个打开命名路由的方法
//打开一个页面
Navigator.of(context).pushNamed(page_routes_appbar,arguments: 'test');
///打开一个页面,并获取他的返回值
Navigator.of(context).pushNamed(page_routes_appbar,arguments: 'test').then((value) => printString(value));
//类似android setResult方法,设置返回值
Navigator.pop(context, "返回值")
MaterialPageRoute
先来看一下构造方法
MaterialPageRoute({
@required this.builder,
RouteSettings settings,
this.maintainState = true,
bool fullscreenDialog = false,
})
MaterialPageRoute是Material 库中提供的组件,针对不同平台使用不同的打开动画,
android 从底部向上打开 从顶部向下关闭
ios 从右向左打开 从左向右关闭
再来看一下他的参数,
builder 返回需要打开的页面
setting 其中包括name 与 arguments 一个是路由器名,还有携带参数
maintainState 源码中是这样描述的, 默认情况下,当入栈一个新路由时,原来的路由仍然会被保存在内存中,如果想在路由没用的时候释放其所占用的所有资源,可以设置maintainState为false。感觉这样会释放他所持有的资源数据,
上面两种方法你都看到有一个arguments的地方我随便写了一个参数,这个就是打开下一个页面携带的入参,在下一个页面获取参数的方法为,
var arguments=ModalRoute.of(context).settings.arguments;
其实对于我来说,这两个打开的方式其实都有点不完美,我先来说一下我的需求吧,
1.最主要的需求,他需要看起来比较清晰,到底打开哪一个页面不能在页面中体现,要不然太乱,
2.可以在打开页面之前做一些判断,比如登录 补全信息等
3.思路清晰
例子
Map<String, Widget> _route = {
page_routes_container: TsmContainerPage(),
page_routes_scaffold: TsmScaffoldPage(),
page_routes_appbar: TsmAppBarPage(),
page_routes_row_and_column: TsmRowAndColumnPage(),
page_routes_text: TsmTextPage(),
page_routes_text_field: TsmTextFieldPage(),
page_routes_raised_button: TsmRaisedButtonPage(),
page_routes_icon: TsmIconPage(),
page_routes_iamge: TsmImagePage(),
page_routes_single_child_scroll_view: TsmSingleChildScrollViewPage(),
page_routes_scroll_base: ScrollBasePage(),
page_routes_grid_view: TsmGridViewPage(),
page_routes_list_view: TsmListViewPage(),
};
MaterialApp(
...//省略属性
/// 经测试onGenerateRoute这个东西必须 与 routes 中的配置互斥,如果在routes 中配置了,则该回调不起作用,
/// 注意这里可以获取到route的name 也就是路由的路径,可以利用map 来操作,先把map加载进来,
/// 如果该路由路径存在于map中则获取map中的widget,如果没在就打开主页
/// 这么做的好处就是便于拦击,还有像命名路由那样,地址与widget 一一对应,非常清晰
onGenerateRoute: (settings) {
printString('onGenerateRoute');
return MaterialPageRoute(builder: (context) {
String routeName = settings.name;
printString(routeName);
if(_route.containsKey(routeName)){
return _route[routeName];
}
return TsmScaffoldPage();
});
},
我学习flutter的整个过程都记录在里面了
https://www.jianshu.com/c/36554cb4c804
最后附上demo 地址
网友评论