6.3 实现基本导航功能
详情页面创建好了,下面可以通过单击Card中的“详情”按钮来切换页面。在News小部件中,单击“详情”按钮时需要执行一些代码,因为只需要执行一行代码,所以可以使用等号加箭头方式编写。可以使用Flutter自带的Navigator,它是flutter/material.dart包中附带的。context管理导航的范围,context知道现在我们在哪个页面,也知道如何导航,所以它是Navigator中必须的。
在main.dart中我们创建了MaterialApp。MaterialApp是导航的重要部分,它能设置页面导航,所以单击“详情”按钮的监听事件不能只使用Navigator,因为News小部件被包含在MaterialApp中,同样HomePage的导航也被包含在MaterialApp中。
在Navigator后面加点,IDE会给出提示,通常如果想加载一个新的页面可以使用push()方法,代码如下所示:
push()方法可以压入一个页面,那么为什么是压入页面呢?因为这是由在Flutter中导航的结构栈决定的。假设有两个页面:资讯列表页面和资讯详情页面,我们希望在它们之间切换,可以通过压入页面和弹出页面来实现。页面被栈管理,我们看到的页面是页面栈中最上面的页面,使用压入的方式可以向栈中添加更多的页面。同时也可以通过弹出栈中的页面来实现返回到之前的页面。
我们看见的一定是最上面的页面,所以可以一直弹出,直到只剩一个页面。以上就是页面导航的工作原理。我们使用的是栈结构,所以这里可以使用push()方法把一个页面压入到栈,那么需要把什么压进去呢?这里不可以压入一个页面,需要压入的是路径route。route不是显示的内容,而是Flutter需要知道的一些信息。把MaterialPageRoute传入,代码如下:
MaterialPageRoute包含路径,例如从一个页面跳转到另一个页面的动画效果,push()方法不仅需要传入路径,还需要另外一个参数作为位置参数中的第一个参数context。context包含有关页面的重要信息,它保留着整个应用环境中的页面的位置,Navigator需要这些信息以便正确地创建一个新的页面,并从当前页面导航到新的页面。
MaterialPageRoute也是Navigator所需要的,MaterialPageRoute告诉Navigator哪个页面应该被压入。在MaterialPageRoute中传入builder参数,builder是一个方法参数,也需要接收context参数,context的类型是BuildContext。下面需要做的是有关页面的,builder的方法将返回一个小部件,然后MaterialPageRoute被告知准备构建此页面,并导航到它,所以这里需要引入这个页面。pages目录下的news_detail.dart,代码如下所示:
在builder这里,把NewsDetailPage实例化,代码如下:
在push()方法中我们添加了一个新的路径,而不是压入页面。路径表示怎样构建一个新的页面。保存并重启应用,单击列表中的“详情”按钮,可以导航到详情页面,详情页面顶部有一个返回按钮,它不是我们编写的,而是Flutter自带的,如图6.2所示。
图6.2 带返回按钮的详情页
单击返回按钮可以返回到之前的页面。我们也可以在详情页面中添加一个按钮来实现返回功能,在文本下面添加一个按钮,按钮中添加单击事件,单击的监听方法中使用Navigator.pop(context),pop()方法是Flutter自带的返回按钮所使用的方法。pop()方法也需要context参数,代码如下:
这样就实现了返回功能。