You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter导航栏中居中悬浮操作按钮的实现问题

解决Flutter导航栏中间嵌入按钮并添加圆形背景的问题

一、让按钮完全位于导航栏中间

要实现按钮完美嵌在导航栏中间,推荐使用BottomAppBar配合FloatingActionButton的方案,通过设置BottomAppBar的缺口形状来精准对齐:

Scaffold(
  floatingActionButton: FloatingActionButton(
    onPressed: () {},
    backgroundColor: Colors.blue, // 自定义按钮背景色
    child: const Icon(PhosphorIcons.plusLight, color: Colors.white),
    elevation: 0, // 去掉阴影让按钮更贴合导航栏
  ),
  floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
  bottomNavigationBar: BottomAppBar(
    shape: const CircularNotchedRectangle(), // 生成适配FAB的中间缺口
    color: Colors.white, // 导航栏背景色
    child: SizedBox(
      height: 60, // 导航栏固定高度
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          // 左侧导航项
          IconButton(
            icon: const Icon(Icons.home),
            onPressed: () {},
          ),
          const SizedBox(width: 40), // 为中间按钮预留空间
          // 右侧导航项
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: () {},
          ),
        ],
      ),
    ),
  ),
);

如果坚持使用原生BottomNavigationBar,需设置偶数个导航项(含中间占位项),并自定义FAB位置确保对齐:

// 自定义FAB位置类
class CustomCenterDocked extends FloatingActionButtonLocation {
  @override
  Offset getOffset(ScaffoldPrelayoutGeometry scaffoldGeometry) {
    final bottomNavBarHeight = scaffoldGeometry.bottomNavigationBarHeight ?? 0;
    final fabSize = scaffoldGeometry.floatingActionButtonSize ?? Size.zero;
    return Offset(
      scaffoldGeometry.scaffoldSize.width / 2 - fabSize.width / 2,
      scaffoldGeometry.scaffoldSize.height - bottomNavBarHeight - fabSize.height / 2,
    );
  }
}

// 页面使用
Scaffold(
  floatingActionButton: FloatingActionButton(
    onPressed: () {},
    child: const Icon(PhosphorIcons.plusLight, color: navBarColor),
  ),
  floatingActionButtonLocation: CustomCenterDocked(),
  bottomNavigationBar: BottomNavigationBar(
    items: const [
      BottomNavigationBarItem(icon: Icon(Icons.home), label: ''),
      BottomNavigationBarItem(icon: SizedBox(), label: ''), // 中间占位项
      BottomNavigationBarItem(icon: Icon(Icons.settings), label: ''),
    ],
    elevation: 0,
  ),
);

二、给导航栏项添加圆形背景

在导航项的图标外层嵌套Container,通过BoxDecoration设置圆形背景,结合InkWell实现点击交互:

// 带圆形背景的导航项示例
InkWell(
  onTap: () {},
  child: Container(
    padding: const EdgeInsets.all(8),
    decoration: BoxDecoration(
      color: isSelected ? Colors.blue : Colors.transparent, // 选中时显示背景色
      shape: BoxShape.circle,
    ),
    child: const Icon(Icons.home, color: Colors.white),
  ),
);

完整结合示例

将两种需求整合后的完整代码:

Scaffold(
  floatingActionButton: FloatingActionButton(
    onPressed: () {},
    backgroundColor: Colors.blue,
    child: const Icon(PhosphorIcons.plusLight, color: Colors.white),
  ),
  floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
  bottomNavigationBar: BottomAppBar(
    shape: const CircularNotchedRectangle(),
    color: Colors.white,
    child: SizedBox(
      height: 60,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          // 首页项(选中状态,带蓝色圆形背景)
          InkWell(
            onTap: () {},
            child: Container(
              padding: const EdgeInsets.all(8),
              decoration: const BoxDecoration(
                color: Colors.blue,
                shape: BoxShape.circle,
              ),
              child: const Icon(Icons.home, color: Colors.white),
            ),
          ),
          const SizedBox(width: 40),
          // 设置项(未选中状态)
          InkWell(
            onTap: () {},
            child: Container(
              padding: const EdgeInsets.all(8),
              decoration: BoxDecoration(
                color: Colors.transparent,
                shape: BoxShape.circle,
              ),
              child: const Icon(Icons.settings, color: Colors.black),
            ),
          ),
        ],
      ),
    ),
  ),
);

内容的提问来源于stack exchange,提问作者user14157206

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 10:54:34