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

Flutter如何实现带流畅动画的动态悬浮按钮自定义底部导航栏

带动态悬浮按钮的自定义底部导航栏实现方案

效果参考

  • 初始状态:
    初始效果示意图
  • Tab切换后状态:
    tab切换后效果示意图

分技术栈实现方案

Android原生(Kotlin)实现

  • 底部导航可以用BottomAppBar搭配BottomNavigationView实现,自带FAB嵌入缺口,也可以自定义ViewGroup绘制个性化的底部导航样式和缺口形状
  • FAB切换动画用ViewPropertyAnimator实现即可,切换逻辑绑定底部导航的选中回调,动画包含缩放、透明度两个维度的过渡即可达到自然的缓动效果,插值器推荐用DecelerateInterpolator
  • 如果需要实现FAB平移联动底部缺口移动的效果,可以动态修改BottomAppBar的shapeAppearance参数,和FAB的位移动画同步执行
  • 核心代码示例:
bottomNav.setOnItemSelectedListener { menuItem ->
    // 匹配当前tab对应的FAB图标和点击逻辑
    val (iconRes, action) = when(menuItem.itemId) {
        R.id.tab_home -> Pair(R.drawable.ic_add, ::onHomeFabClick)
        R.id.tab_mine -> Pair(R.drawable.ic_edit, ::onMineFabClick)
        else -> Pair(R.drawable.ic_default, ::onDefaultFabClick)
    }
    // 执行退出动画
    fab.animate()
        .scaleX(0f).scaleY(0f).alpha(0f)
        .setDuration(150)
        .setInterpolator(DecelerateInterpolator())
        .withEndAction {
            // 更新FAB属性后执行进入动画
            fab.apply {
                setImageResource(iconRes)
                setOnClickListener { action() }
                animate()
                    .scaleX(1f).scaleY(1f).alpha(1f)
                    .setDuration(150)
                    .setInterpolator(DecelerateInterpolator())
                    .start()
            }
        }
        .start()
    true
}

Flutter实现

  • 底部导航可以直接用Scaffold的bottomNavigationBar参数传入自定义的导航组件,也可以用convex_bottom_bar等成熟的第三方库快速实现带缺口的底部导航样式
  • FAB的切换动画直接用AnimatedSwitcher组件封装即可,内置的过渡动画可以满足大部分需求,也可以自定义过渡效果实现更个性的动画
  • 核心代码示例:
Scaffold(
  bottomNavigationBar: BottomNavigationBar(
    currentIndex: _selectedIndex,
    onTap: (index) => setState(() => _selectedIndex = index),
    items: const [
      BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
      BottomNavigationBarItem(icon: Icon(Icons.person), label: "我的")
    ]
  ),
  floatingActionButton: AnimatedSwitcher(
    duration: const Duration(milliseconds: 300),
    transitionBuilder: (child, animation) => ScaleTransition(
      scale: animation,
      child: FadeTransition(opacity: animation, child: child),
    ),
    child: FloatingActionButton(
      key: ValueKey(_selectedIndex),
      onPressed: _selectedIndex == 0 ? () => onHomeFabTap() : () => onMineFabTap(),
      child: Icon(_selectedIndex == 0 ? Icons.add : Icons.edit),
    ),
  ),
  floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
)

注意事项

  • 动画时长建议控制在200-300ms区间,过长会让操作感知卡顿,过短会失去过渡的自然感
  • FAB的点击逻辑要和当前选中的tab强绑定,避免切换动画过程中点击触发错误逻辑
  • 如果需要实现FAB在不同位置之间平移的效果,额外补充位移动画和底部导航的缺口位置动画同步执行即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 05:18:02