Flutter学习笔记之-路由和导航

Flutter学习笔记之-路由和导航

在iOS原生开发中页面的跳转是通过UINavigationController来实现的,而Flutter中页面的跳转是通过Navigator和Route来实现的。

  • 页面的基本跳转案例

案例包括页面跳转到下一个页面,返回上一个页面。

// 第一个页面,通过点击按钮跳转
class DemoWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FlatButton(
      child: Text("跳转下一个页面"),
      onPressed: () {
        Navigator.of(context).push(
            MaterialPageRoute(builder: (context) {
              return SecondPage();
            })
        );
      },
    );
  }
}

// 第二个页面,点击按钮返回上一个页面
class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text("第二个页面")
        ),
        body: Center(
          child: Column(children: <Widget>[
            Text("第二个页面"),
            FlatButton(child: Text("返回上一个页面"), onPressed: () => Navigator.pop(context),)
          ], mainAxisAlignment: MainAxisAlignment.center,
          ),
        )
    );
  }
}
  • 页面之间跳转参数的传递

参数的传递包括:
1、上一个页面向下一个页面传递参数
2、返回上一个页面传递参数

方法一:通过下一个页面的构造函数传递参数

class DemoWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FlatButton(
      child: Text("跳转下一个页面"),
      onPressed: () {
        Future result = Navigator.of(context).push(
            MaterialPageRoute(builder: (context) {
              // 采用构造函数的方式传递参数
              return SecondPage("首页传递的数据");
            })
        );
        // 这里接收pop回来的数据
        result.then((value) {
          print("接收pop回来的值 $value");
        });
      },
    );
  }
}

class SecondPage extends StatelessWidget {
  final String name;
  SecondPage(this.name);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text("第二个页面")
        ),
        body: Center(
          child: Column(children: <Widget>[
            Text("第二个页面 - 接收首页传递的参数 name = ${this.name}"),
            FlatButton(child: Text("返回上一个页面"), onPressed: () {
              _backLastPage(context);
            },)
          ], mainAxisAlignment: MainAxisAlignment.center,
          ),
        )
    );
  }

  void _backLastPage(BuildContext context) {
  // 向上一个页面pop返回参数
    Navigator.pop(context, "返回上一个页面 参数 value = 3");
  }
}

在这里插入图片描述

  • 默认返回按钮的修改以及事件的监听

由上图可以知道push到写一个页面的时候,第二个页面默认会有一个返回按钮,
那么问题来了:
1、如何修改默认的返回按钮样式呢?
2、如何监听当前页面pop事件呢(或者叫点击了默认返回按钮截取这个事件)?

1、首先来修改默认返回按钮的样式和点击事件。
这里利用AppBar中leading替换原有的默认返回按钮并编写自己的事件。

class SecondPage extends StatelessWidget {
  final String name;
  SecondPage(this.name);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text("第二个页面"),
          // 替换原有的返回按钮事件
          leading: FlatButton(
            child: Icon(Icons.arrow_back, color: Colors.white,),
            onPressed: () => _backLastPage(context),
          ),
        ),
        body: Center(
          child: Column(children: <Widget>[
            Text("第二个页面 - 接收首页传递的参数 name = ${this.name}"),
            FlatButton(child: Text("返回上一个页面"), onPressed: () {
              _backLastPage(context);
            },)
          ], mainAxisAlignment: MainAxisAlignment.center,
          ),
        )
    );
  }

  void _backLastPage(BuildContext context) {
    print("_backLastPage");
    Navigator.pop(context, "返回上一个页面 value = 3");
  }
}

这里将默认的返回按钮修改成一个箭头按钮了.

在这里插入图片描述

2、如果任然使用默认的返回按钮,那么怎么样来截获点击按钮之后的事件处理呢?

这里将使用一个WillPopScope的widget来实现。当页面widget将要pop的时候就会触发
WillPopScope中的onWillPop方法。

class SecondPage extends StatelessWidget {
  final String name;
  SecondPage(this.name);

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {
        // 监听pop事件
        _backLastPage(context);
        return Future.value(true);
      },
      child: Scaffold(
          appBar: AppBar(
            title: Text("第二个页面"),
          ),
          body: Center(
            child: Column(children: <Widget>[
              Text("第二个页面 - 接收首页传递的参数 name = ${this.name}"),
              FlatButton(child: Text("返回上一个页面"), onPressed: () {
                _backLastPage(context);
              },)
            ], mainAxisAlignment: MainAxisAlignment.center,
            ),
          )
      ),
    );
  }

  void _backLastPage(BuildContext context) {
    print("_backLastPage");
    Navigator.pop(context, "返回上一个页面 value = 3");
  }
}
  • 命名路由的基本使用
// 首先定义路由映射规则
class RouterConfig {
  static const HomePageRouteName = "/home";
  static const LoginPageRouteName = "/login";
  static const MainPageRouteName = "/main";
  static const OtherPageRouteName = "/other";
  
  static final Map<String, WidgetBuilder> routesMap = {
    RouterConfig.MainPageRouteName: (context) => MainPage(),
    RouterConfig.HomePageRouteName: (context) => HomePage(),
    RouterConfig.LoginPageRouteName: (context) => LoginPage(),
    RouterConfig.OtherPageRouteName: (context) => OtherPage()
  };
}

// 在MaterialApp中设置路由规则和初始化路由
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      key: UniqueKey(),
      title: "Welcome to Flutter",
      initialRoute: RouterConfig.MainPageRouteName,
      routes: RouterConfig.routesMap,
    );
  }
}

// 利用路由名称跳转下一个页面
class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Text("Welcome to Flutter")
      ),
      body: Center(
        child: FlatButton(
          child: Text("跳转下一个页面"),
          onPressed: () {
            Navigator.pushNamed(context, RouterConfig.HomePageRouteName);
          },
        ),
      ),
    );
  }
}
  • 命名路由参数的传递
// Navigator.pushNamed 携带参数
class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Text("Welcome to Flutter")
      ),
      body: Center(
        child: FlatButton(
          child: Text("跳转下一个页面"),
          onPressed: () {
            Navigator.pushNamed(context, RouterConfig.HomePageRouteName, arguments: "命名路由的参数传递");
          },
        ),
      ),
    );
  }
}

// 在HomePage中接收传递过来额参数
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 获取命名路由传递过来的参数
    Object arguments = ModalRoute.of(context).settings.arguments;
    String name = ModalRoute.of(context).settings.name;
    print("获取传递过来的参数 arguments = $arguments - name = $name");

    return Scaffold(
      appBar: AppBar(
        title: Text("Home Page"),
      ),
      body: Center(
        child: Text("home"),
      ),
    );
  }
}

上面传递的方式是HomePage页面没有带参数的构造方式,如果HomePage只提供了带参数的构造函数,那么在MaterialApp中构建routes时创建HomePage就不太合适了。
下面就利用onGenerateRoute函数来解决这种情况。

// 跳转方式不用变化,依然采用这种方式
Navigator.pushNamed(context, RouterConfig.HomePageRouteName, arguments: "命名路由的参数传递");

// 在构造routes就需要做一些改变了
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      key: UniqueKey(),
      title: "Welcome to Flutter",
      initialRoute: RouterConfig.MainPageRouteName,
      routes: RouterConfig.routesMap,
      // 核心修改点
      onGenerateRoute: (setting) {
        if (setting.name == RouterConfig.HomePageRouteName) {
          return MaterialPageRoute(builder: (context) {
            // 采用构造函数的方式传递参数
            return HomePage(setting.arguments);
          });
        }
        return null;
      },
    );
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值