Flutter学习之Navigate

334 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情

本文主要介绍下Navigate的使用

1. Navigator

Navigator 是一个组件,管理和维护一个基于堆栈的历史记录,通过 push 和 pop 进行页面的跳转。

class PageA extends StatelessWidget {
  const PageA({Key? key}) : super(key: key);

  @override

  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(color: Colors.orangeAccent,),
      floatingActionButton: FloatingActionButton(onPressed: () { Navigator.of(context).push(MaterialPageRoute(builder: (context) => PageB())); },),
    );
  }
}

页面B

class PageB extends StatelessWidget {
  const PageB({Key? key}) : super(key: key);

  @override

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('页面B'),),
      body: Container(color: Colors.red,),
    );
  }
}

iShot_2022-08-25_17.44.14.gif

当应用程序位于A页面时,路由堆栈中只有A,点击按钮跳转到B页面,路由堆栈中有 B 和 A,且 B 处于栈顶。

通过push进栈,pop出栈。

当我们的栈只有一个的时候进行pop

child: ElevatedButton(
  onPressed: (){
    if(Navigator.of(context).canPop()){
      Navigator.of(context).pop();
    }
  },

2. pushNamed

pushNamed 是命名路由的方式,需要在 MaterialApp 中配置路由名称:

MaterialApp(
      title: 'Router Demo',
      routes: <String, WidgetBuilder>{
        '/A': (context) => PageA(),
        '/B': (context) => PageB(),
      },
      home: Scaffold(
        body: PageA(),
      ),
    )

跳转

ElevatedButton(
  onPressed: (){
  Navigator.of(context).pushNamed('/B');
  },
  child: Text('push B'),

)

当我们有三个页面的时候,从B push C

ElevatedButton(
  onPressed: (){
  Navigator.of(context).pushReplacementNamed('/C');
  },
  child: Text('push C'),

)

C返回的时候直接到达页面A

iShot_2022-08-25_18.03.12.gif

  • popAndPushNamed
ElevatedButton(
  onPressed: (){
    // Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=>PageC()));
    Navigator.of(context).popAndPushNamed('/C');
  },
  child: const Text('push B'),

popAndPushNamed 路由堆栈和 pushReplacementNamed 是一样,唯一的区别就是 popAndPushNamed 有 B 页面退出动画。

popAndPushNamedpushReplacementNamed 使当前页面不在路由堆栈中,所以通过 pop 无法返回此页面。

适用场景:

 1.   **欢迎页面**:应用程序打开后首先进入欢迎界面,然后进入首页,进入首页后不应该再进入欢迎界面。
 2.  **登录页面**:登录成功后进入相关页面,此时按返回按钮,不应再进入登录页面。
  • pushNamedAndRemoveUntil

适用于特定入口场景,比如我们在登陆流程中进行注册或者绑定,之后我们就不希望在返回该路径

pushNamedAndRemoveUntil进入 D 页面同时删除路由堆栈中直到 /B 的路由,C 页面代码:

Navigator.of(context).pushNamedAndRemoveUntil('/D', ModalRoute.withName('/B'));

A->B->C->D之后 返回B

3. 传递数据

  • 通过构造函数
class PageB extends StatelessWidget {
  final String title;
   const PageB({Key? key,required this.title}) : super(key: key);

  @override

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title:  Text(title),),
      body: Center(
        child: ElevatedButton(
          onPressed: (){
            // Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=>PageC()));
            Navigator.of(context).popAndPushNamed('/C');
          },
          child: const Text('push B'),

        ),

      ),
    );
  }
}

跳转

Navigator.of(context).push(MaterialPageRoute(builder: (context) => const PageB(title: "页面B",)));
  • 通过命名路由设置参数的方式:
FloatingActionButton(onPressed: (){


    Navigator.of(context).pop();
  },
     child: Text('${ModalRoute.of(context)?.settings.arguments}'),
)
  • 接受
Navigator.of(context).pop("你好");

跳转页面接受

class PageB extends StatefulWidget {
  final String title;
  const PageB({Key? key,required this.title}) : super(key: key);
  @override
  State<PageB> createState() => _PageBState();
}

class _PageBState extends State<PageB> {
 var  arg = '"';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title:  Text(arg),),
      body: Center(
        child: ElevatedButton(
          onPressed: () async{
            // Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=>PageC()));
          var result = await Navigator.of(context).pushNamed('/C',arguments: "hello") as String;
          setState(() {
            arg = result;
          });

          },
          child: const Text('push B'),

        ),

      ),
    );
  }
}

iShot_2022-08-25_22.34.02.gif