参考英文地址:Flutter — PageView with BottomNavigationBar
你可能早已经使用过BottomNavigation和PageView。
现在,我们将要一起使用这个两个组件。
第一步
创建一个BottomNavigationBar和三个BottomNavigationBarItem。
这个BottomNavigationBar用于在应用的底部展示,用于视图的选择,通常大多是3个到5个之间,底部导航常由文本标签、图标或两者兼有的多种形式的项组成,提供了应用底层视图之间的快速导航,这个底部导航常常与 Scaffold配合使用,这个脚手架提供了Scaffold.bottomNavigationBar 参数。
底部导航栏类型决定了这些导航项如何展示,如果没有指定,当少4个的时候,自动设置为 BottomNavigationBarType.fixed,如果 fixedColor 指定了,将以该颜色渲染选中的导航项,未指定将会使用ThemeData.primaryColor,导航栏的背景色,默认为(ThemeData.canvasColor)Material的背景色(不透明白色),当大于等于4个的时候,设置为BottomNavigationBarType.shifting ,所有的导航项被渲染为白色,导航栏的背景色与选中导航项的背景色一致,会fixed不同的是,每点击一导航项,会有一个动画效果。
这个BottomNavigationBarItem类很少单独使用。通常嵌入在上面的一个底部导航小部件中。
1 | int bottomSelectedIndex = 0; |
第二步
使用3个状态组件创建PageView。
PageView是按页展示的滚动列表。
页面视图的子组件被强制与视图窗口的大小保持一致,你可以使用PageController来控制在这个视图中可见的页面,视窗。
您可以使用PageController来控制哪个页面在视图中可见。除了能够控制PageView中内容的像素偏移量之外,PageController还允许您以页面的形式控制偏移量,即以视图窗口大小为增量。
PageController也用于控制PageController.initialPage,它决定了在初次构造PageView时显示哪个页面,以及PageController,以及PageController.viewportFraction,它决定了页面大小占视窗大小的百分比,keepPage参数决定了是否使用PageStorage 保存当前页面。
第一个页面,red.dart
1 |
|
第二个页面,blue.dart
1 | class Blue extends StatefulWidget { |
第三个页面,yellow.dart
1 | class Yellow extends StatefulWidget { |
我们需要传入PageController来控制初始化选择的页面,以及手动地从一个导航到另一页面。
1 | PageController pageController = PageController( |
在build方法体中调用buildPageView。
1 |
|
第三步
我们需要做一些技巧来管理PageView和BottomNavigationBar的同步。
在当前应用程序中的状态中,有两个问题:
- 当我们滑动导航栏时,它的选择不会改变。
- 当我们选择其他的底部导航栏项时,我们的页面视图不会滚动。
为了解决第一问题,我们可以使用由PageView提供的onPageChanged事件。
1 | void pageChanged(int index) { |
onPageChanged事件将会给我们当前页面的索引,我接受到页面索引在setState中设置bottomSelectedIndex索引,这样我们的底部的选择就会自动变化。
现在修复第二个问题,如果我们选择任意的BottomNavigationBarItem,然后我们的PageView应该自动滑动,为了修复这个问题,我们需要使用BottomNavigationBar的onTap事件。
1 |
|
类似于onPageChanged事件,onTap事件也为我们提供了当前触碰的一个索引,这样基于这个索引设置bottomSelectedIndex,然后使用pageController.animateToPage移动选中的页面,其接受三个参数,index,duation,curve,返回一个future。
1 | pageController.animateToPage(index, duration: Duration(milliseconds: 500), curve: Curves.ease); |

最终的main.dart文件如下:
1 |
|