底部导航 参考
1、普通效果:我们可以通过
Scaffold
的bottomNavigationBar
属性来设置底部导航,通过Material组件库提供的BottomNavigationBar
和BottomNavigationBarItem
两种组件来实现Material风格的底部导航栏。
2、如图效果:Material组件库中提供了一个BottomAppBar
组件,它可以和FloatingActionButton
配合实现这种“打洞”效果。
实现如图“打洞”效果
底部
BottomAppBar
的child
设置为Row
,并且将Row
用其children
5 等分,中间的位置空出(我的实现方法)。在Scaffold
中设置floatingActionButton
,并且设置floatingActionButtonLocation
为FloatingActionButtonLocation.centerDocked
。
代码如下:
Scaffold(
//...省略部分代码
floatingActionButton: FloatingActionButton(
//悬浮按钮
child: Icon(Icons.add),
onPressed: () {}),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
body: pages[currentIndex],
bottomNavigationBar: BottomAppBar(
child: Row(
children: <Widget>[
SizedBox(height: 49, width: itemWidth, child: bottomAppBarItem(0)),
SizedBox(height: 49, width: itemWidth, child: bottomAppBarItem(1)),
SizedBox(height: 49, width: itemWidth),
SizedBox(height: 49, width: itemWidth, child: bottomAppBarItem(2)),
SizedBox(height: 49, width: itemWidth, child: bottomAppBarItem(3))
],
mainAxisAlignment: MainAxisAlignment.spaceAround,
),
shape: CircularNotchedRectangle(),
),
);
自定义 Item View
上述代码中,其中4个item都是
SizedBox(height: 49, width: itemWidth, child: bottomAppBarItem(0))
(中间的为空白,itemWidth
为double itemWidth = MediaQuery.of(context).size.width / 5;
)。bottomAppBarItem
方法,传入底部导航item的index
,返回Widget
,代码如下:
Widget bottomAppBarItem(int index) {
//设置默认未选中的状态
TextStyle style = TextStyle(fontSize: 12, color: Colors.black);
String imgUrl = normalImgUrls[index];
if (currentIndex == index) {
//选中的话
style = TextStyle(fontSize: 13, color: Colors.blue);
imgUrl = selectedImgUrls[index];
}
//构造返回的Widget
Widget item = Container(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Image.asset(imgUrl, width: 25, height: 25),
Text(
titles[index],
style: style,
)
],
),
onTap: () {
if (currentIndex != index) {
setState(() {
currentIndex = index;
});
}
},
),
);
return item;
}
变量解释
pages
为要显示的每一页Widget;
currentIndex
表示当前选中底部item的index;
titles
底部item显示的文字列表;
normalImgUrls
为未选中状态的图片地址列表;
selectedImgUrls
为选中状态的图片地址列表。
未选中与选中状态
Image
和Text
默认设为未选中图片及样式,判断如果currentIndex == index
的话,就改为选中状态图片及样式,这样构建item的时候就可以。
点击切换
在每个item的
onTap
事件中如果currentIndex != index
(不处理点击当前选中的item的情况) 则currentIndex = index,
调用setState()
重新build
,body: pages[currentIndex]
即可显示最新的页面。
Tips
现在虽然实现了简单的效果,但是尚有不足,优化篇了解一下。