一、效果
二、核心思路
利用floatingActionButton结合BottomAppBar,使得floatingActionButton悬浮在BottomAppBar之上,以达到中心凸起的效果。
三、BottomAppBar部分代码参考
Widget myBottomAppBar() {
return BottomAppBar(
height: 80,
color: Colors.blue.withOpacity(0.5),
// 底部导航栏的形状,可以让中间按钮凸出
shape: const CircularNotchedRectangle(),
notchMargin: 10,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
InkWell(
// 去除InkWell的点击效果
splashFactory: NoSplash.splashFactory,
onTap: () {
// 使用的页面控制器切换页面
_pageController.jumpToPage(0);
setState(() {
currentPage = 0;
});
},
child: Column(
children: [
Icon(
Icons.home,
color: Colors.white,
size: currentPage == 0 ? 45 : 24,
),
const SizedBox(
height: 3,
),
Visibility(
visible: currentPage != 0,
child: const Text(
"HOME",
style: TextStyle(fontSize: 12, color: Colors.white),
),
),
],
),
),
// 空间占位符,为了让两侧的图标和中间的按钮保持间隔
// width设置数值越大,两侧的导航图标离中间的按钮越远
const SizedBox(
width: 0,
),
InkWell(
// 去除InkWell的点击效果
splashFactory: NoSplash.splashFactory,
onTap: () {
_pageController.jumpToPage(1);
setState(() {
currentPage = 1;
});
},
child: Column(
children: [
Icon(
Icons.message,
color: Colors.white,
size: currentPage == 1 ? 45 : 24,
),
const SizedBox(
height: 3,
),
Visibility(
visible: currentPage != 1,
child: const Text(
"MESSAGE",
style: TextStyle(fontSize: 12, color: Colors.white),
),
),
],
),
),
],
),
);
}
四、floatingActionButton部分代码参考
floatingActionButton要求的属性为Widget,我这里写了SizedBox嵌套FloatingActionButton是为了控制按钮的大小。
floatingActionButton: SizedBox(
width: 66,
height: 66,
child: FloatingActionButton(
onPressed: () {
// MyToast是我写的自定义Toast
MyToast.showShortToast("floatingActionButton");
},
// 设置按钮的背景颜色
backgroundColor: Colors.white,
// 确保按钮是圆形的
shape: const CircleBorder(),
elevation: 10.0,
child: const Icon(Icons.center_focus_weak),
),
),
// 使得按钮居中显示
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
五、引用代码参考
List<Widget> tabs = [const PageA(), const PageB()];
final PageController _pageController = PageController();
int currentPage = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: myBottomAppBar(),
floatingActionButton: SizedBox(
width: 66,
height: 66,
child: FloatingActionButton(
onPressed: () {
MyToast.showShortToast("floatingActionButton");
},
// 设置按钮的背景颜色
backgroundColor: Colors.white,
// 确保按钮是圆形的
shape: const CircleBorder(),
elevation: 10.0,
child: const Icon(Icons.center_focus_weak),
),
),
// 使得按钮居中显示
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
body: PageView(
physics: const NeverScrollableScrollPhysics(),
controller: _pageController,
children: tabs,
onPageChanged: (int index) {
setState(() {
currentPage = index;
});
},
),
);
}
六、总结
需要注意的是,BottomAppBar中的占位符是一定要写的,哪怕SizedBox的width为0,我尝试了删掉SizedBox,无法达到显示效果。