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

Flutter实现凹陷式底部导航栏时凹槽位置偏移问题求助

Flutter BottomAppBar圆形凹陷错位修复

问题现象

目标实现带中心圆形凹陷的悬浮底部导航效果,参考设计如下:
参考设计效果
编写代码运行后出现凹陷位置与悬浮按钮错位的异常,效果如下:
凹陷错位异常
原有问题代码:

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;
    return Scaffold(
        floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
        floatingActionButton: FloatingActionButton(
          onPressed: () {},
          child: Icon(Icons.add),
          elevation: 2.0,
        ),
        bottomNavigationBar: Padding(
          padding: const EdgeInsets.only(left: 32.0, right: 32.0, bottom: 32.0),
          child: BottomAppBar(
            child: Row(
              mainAxisSize: MainAxisSize.max,
              children: <Widget>[
                Expanded(
                  child: Image.asset('assets/images/account.png',
                      width: 32.0, height: 32.0, fit: BoxFit.contain),
                ),
                Expanded(
                  child: Image.asset('assets/images/settings.png',
                      width: 32.0, height: 32.0, fit: BoxFit.contain),
                )
              ],
            ),
            shape: CircularNotchedRectangle(),
            color: Colors.white,
          ),
        ),
        body: Center(
          child: Text('Home Page'),
        ));
  }
}

错位原因

  • CircularNotchedRectangle 是基于BottomAppBar自身占满的底部导航区域和FAB的相对位置计算凹陷位置的。在BottomAppBar外层包裹左右、底部边距,会压缩BottomAppBar自身的渲染范围,导致它计算FAB相对位置时出现偏差,凹陷和FAB自然错位。
  • BottomAppBar内部的Row用两个Expanded均分全部宽度,没有给中心悬浮按钮预留空位,会导致两侧图标被凹陷区域遮挡。
  • 直接给BottomAppBar加外层边距时,悬浮按钮的垂直位置没有同步适配,也会加重错位问题。

修复方案

  • 不要在BottomAppBar外层直接加边距,将BottomAppBar本身设为透明、占满整个底部导航区域,边距、圆角、背景样式全部放到BottomAppBar内部的容器上,保证BottomAppBar能正确获取FAB的相对位置,让凹陷和FAB完全对齐。
  • 在导航栏行布局的两个图标中间插入固定宽度的占位组件,预留出FAB和凹陷的位置,避免图标被遮挡。
  • 给Scaffold设置extendBody: true,让页面内容延伸到导航栏下方,实现设计图的悬浮通透效果,按需调整notchMargin参数控制凹陷和FAB的间距即可。

修复后可直接运行的代码

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBody: true,
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.add),
        elevation: 2.0,
      ),
      bottomNavigationBar: BottomAppBar(
        color: Colors.transparent,
        elevation: 0,
        // 控制凹陷和FAB的间距
        notchMargin: 8.0,
        clipBehavior: Clip.antiAlias,
        shape: const CircularNotchedRectangle(),
        child: Padding(
          // 原外层边距移到BottomAppBar内部,不影响位置计算
          padding: const EdgeInsets.only(left: 32.0, right: 32.0, bottom: 32.0),
          child: Container(
            height: 64,
            decoration: const BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.all(Radius.circular(24)),
            ),
            child: Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                IconButton(
                  icon: Image.asset('assets/images/account.png',
                      width: 32.0, height: 32.0, fit: BoxFit.contain),
                  onPressed: () {},
                ),
                // 中间占位,预留FAB和凹陷位置
                const SizedBox(width: 56),
                IconButton(
                  icon: Image.asset('assets/images/settings.png',
                      width: 32.0, height: 32.0, fit: BoxFit.contain),
                  onPressed: () {},
                ),
              ],
            ),
          ),
        ),
      ),
      body: const Center(
        child: Text('Home Page'),
      ),
    );
  }
}

提示:如果运行后凹陷和FAB的贴合度不符合预期,可以微调notchMargin数值和中间占位SizedBox的宽度,直到和设计效果完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 14:42:33