Flutter-路由导航

Flutter-路由导航,第1张

文章目录 Route & NavigatorRouteNavigator 1.路由基本使用1.1 基本跳转1.2 参数传递 2.命名路由2.1 基本使用2.2 命名规范化2.3 参数传递2.4 路由钩子2.4.1 onGenerateRoute2.4.2 onUnknownRoute 2.5 其它路由跳转

Route & Navigator

Flutter中,路由管理主要有两个类:Route和Navigator

Route

Route:一个页面要想被路由统一管理,必须包装为一个Route。
但是Route是一个抽象类,所以它是不能被实例化的,实际开发中使用的是MaterialPageRoute,MaterialPageRoute并不是Route的直接子类。

MaterialPageRoute -> PageRoute -> ModalRoute -> TransitionRoute -> OverlayRoute -> Route

MaterialPageRoute在不同的平台有不同的表现:

在Android平台,打开一个页面会从屏幕底部滑动到屏幕的顶部,关闭页面时从顶部滑动到底部消失在iOS平台,打开一个页面会从屏幕右侧滑动到屏幕的左侧,关闭页面时从左侧滑动到右侧消失。当然,iOS平台我们也可以使用CupertinoPageRoute Navigator

Navigator:管理所有的Route的Widget,通过一个Stack来进行管理的
开发中无需手动去创建Navigator,因为开发中使用的MaterialApp、CupertinoApp、WidgetsApp默认有Navigator,直接使用即可

基本使用方法:
Navigator.push(context, route);
Navigator.pushNamed(context, routeName);
Navigator.pop(context);
1.路由基本使用 1.1 基本跳转 创建首页页面,中间添加一个按钮,点击按钮跳转到详情页面创建详情页面,中间添加一个按钮,点击按钮返回到首页页面
  //按钮点击执行的代码
  void _jumpToNextPage(BuildContext context){
    Navigator.of(context).push(MaterialPageRoute(builder: (ctx){
      return MaterialsPutInPage();
    }));
  }
  //按钮点击执行的代码
  void goBack(){
    Navigator.of(context).pop();
  }
1.2 参数传递 首页跳到详情页,携带一条信息’a home message’详情页返回首页,携带一条信息’a detail message’

首页核心代码:

在页面跳转时,会返回一个Future该Future会在详情页面调用pop时,回调对应的then函数,并且会携带结果
  //首页按钮点击执行的代码
  void _jumpToNextPage(BuildContext context){
    //1.跳转代码
    final future = Navigator.of(context).push(MaterialPageRoute(builder: (ctx){
      return MaterialsPutInPage("a home message");
    }));
    //2.获取结果
    future.then((value) => print(value));
  }
  //详情页接收数据
  final String message;
  MaterialsPutInPage(this.message);
  //详情页按钮点击执行的代码
  void goBack(){
    Navigator.of(context).pop("a detail message");
  }
2.命名路由 2.1 基本使用

我们可以通过创建一个新的Route,使用Navigator来导航到一个新的页面,但是如果在应用中很多地方都需要导航到同一个页面,那么就会存在很多重复的代码。

在这种情况下,我们可以使用命名路由(named route)

命名路由是将名字和路由的映射关系,在一个地方进行统一的管理有了命名路由,我们可以通过Navigator.pushNamed()方法来跳转到新的页面

命名路由在哪里管理呢?可以放在MaterialApp的initialRoute和routes中

initialRoute:设置应用程序从哪一个路由开始启动,设置了该属性,就不需要再设置home属性了routes:定义名称和路由之间的映射关系,类型为Map

修改MaterialApp中的代码

return MaterialApp(
  title: Strings.home_title,
  theme: ThemeData(
    primaryColor: Colors.red
  ),
  routes: {
    "/" : (ctx)=> HomePage(),
    "/material" : (ctx) => MaterialsPutInPage(),
  },
  //home: HomePage(),
  initialRoute: "/",
);

修改跳转的代码

  void _jumpToNextPage(BuildContext context){
    // Navigator.of(context).push(MaterialPageRoute(builder: (ctx){
    //   return MaterialsPutInPage();
    // }));
    Navigator.of(context).pushNamed("/material");
  }
2.2 命名规范化

在开发中,为了让每个页面对应的routeName统一,我们通常会在每个页面中定义一个路由的常量来使用

class AboutPage extends StatelessWidget {
  static const String routeName = "/about";
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

class MaterialsPutInPage extends StatefulWidget {
  static const String routeName = "/materials/putin";
  @override
  _MaterialsPutInPageState createState() => _MaterialsPutInPageState();
}

修改MaterialApp中routes的key

return MaterialApp(
  title: Strings.home_title,
  theme: ThemeData(
    primaryColor: Colors.red
  ),
  routes: {
    HomePage.routeName : (ctx)=> HomePage(),
    MaterialsPutInPage.routeName : (ctx) => MaterialsPutInPage(),
    AboutPage.routeName : (ctx) => AboutPage()
  },
  //home: HomePage(),
  initialRoute: HomePage.routeName,
);

修改跳转代码

Navigator.of(context).pushNamed(MaterialsPutInPage.routeName);
2.3 参数传递

pushName时,传递参数

 Navigator.of(context).pushNamed(MaterialsPutInPage.routeName,arguments: "a home message");

详情页中获取参数
在build方法中ModalRoute.of(context)可以获取到传递的参数

//1.获取数据
    final message = ModalRoute.of(context).settings.arguments;

接收返回值

  void _jumpToNextPage(BuildContext context){
     //1.跳转代码
    var future = Navigator.of(context).pushNamed(MaterialsPutInPage.routeName,arguments: "a home message");
    //2.获取结果
    future.then((value) => print(value));
  }
//返回时传递参数
Navigator.of(context).pop("返回值");
2.4 路由钩子 2.4.1 onGenerateRoute

假设我们有一个页面AboutPage,也希望在跳转时,传入对应的参数message,并且已经有一个对应的构造方法
AboutPage代码

class HYAboutPage extends StatelessWidget {
  staticconstString routeName = "/about";
  finalString message;

  HYAboutPage(this.message);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("关于页面"),
      ),
      body: Center(
        child: Text(message, style: TextStyle(fontSize: 30, color: Colors.red),),
      ),
    );
  }
}

首页跳转代码

RaisedButton(
  child: Text("打开关于页"),
  onPressed: () {
    Navigator.of(context).pushNamed(HYAboutPage.routeName, arguments: "a home message");
  },
)

此时如果继续使用routes中的映射关系,就不好进行配置了,因为AboutPage要求必须传入一个参数
这个时候我们可以使用onGenerateRoute的钩子函数:

当我们通过pushName进行跳转,但是对应的name在routes中没有映射关系,那么就执行onGenerateRoute钩子函数我们可以在该函数中,手动创建对应的Route进行返回该函数有一个参数RouteSettings,该类有两个常用的属性: name:跳转的路径名称arguments:跳转时携带的参数
onGenerateRoute: (settings) {
  if (settings.name == "/about") {
    return MaterialPageRoute(
      builder: (ctx) {
        return HYAboutPage(settings.arguments);
      }
    );
  }
  returnnull;
},
2.4.2 onUnknownRoute

如果我们打开的一个路由名称是根本不存在的,这个时候我们希望跳转到一个统一的错误页面。

如果没有进行特殊的处理,那么Flutter会报错
RaisedButton(
  child: Text("打开未知页面"),
  onPressed: () {
    Navigator.of(context).pushNamed("/abc");
  },
)
创建错误跳转页面
class UnknownPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("错误页面"),
      ),
      body: Container(
        child: Center(
          child: Text("页面跳转错误"),
        ),
      ),
    );
  }
}
设置onUnknownRoute
onUnknownRoute: (settings) {
  return MaterialPageRoute(
    builder: (ctx) {
      return UnknownPage();
    }
  );
},
2.5 其它路由跳转
Navigator.of(context).pop();
Navigator.of(context).popAndPushNamed(routeName);
Navigator.of(context).popUntil((route) => false);
Navigator.of(context).pushNamed(routeName);
Navigator.of(context).pushReplacementNamed(routeName);
Navigator.of(context).pushNamedAndRemoveUntil(newRouteName, (route) => false);

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/990587.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存