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

如何在Flutter中实现底部导航栏的果冻式动画?

Flutter底部导航栏果冻式动画实现方案

要实现你展示的果冻式弹性底部导航栏,核心是利用Flutter的物理动画系统模拟弹簧形变效果,以下是完整的实现示例:

核心实现逻辑

  • 使用SpringSimulation创建符合果冻弹性特性的动画曲线,相比普通曲线更贴近真实的弹性形变
  • 为底部导航项绑定点击事件,触发动画重置与播放
  • 通过AnimatedBuilder配合Transform实现图标的缩放/位移动画

完整可运行代码

import 'package:flutter/material.dart';
import 'package:flutter/physics.dart';

class JellyBottomNavBar extends StatefulWidget {
  const JellyBottomNavBar({super.key});

  @override
  State<JellyBottomNavBar> createState() => _JellyBottomNavBarState();
}

class _JellyBottomNavBarState extends State<JellyBottomNavBar> with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _jellyAnimation;
  int _currentTab = 0;

  @override
  void initState() {
    super.initState();
    // 初始化动画控制器
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 600),
    );

    // 配置弹簧参数,调节数值可改变果冻弹性
    final springSimulation = SpringSimulation(
      const SpringDescription(
        mass: 0.4,
        stiffness: 180,
        damping: 12,
      ),
      0.0,
      1.0,
      0.0,
    );

    _jellyAnimation = CurvedAnimation(
      parent: _animationController,
      curve: SpringCurve(springSimulation),
    );
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  void _switchTab(int index) {
    if (_currentTab != index) {
      setState(() => _currentTab = index);
      // 重置并播放动画
      _animationController.reset();
      _animationController.forward();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('果冻导航栏示例')),
      body: const Center(child: Text('当前页面内容')),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentTab,
        selectedItemColor: Colors.blue,
        unselectedItemColor: Colors.grey,
        onTap: _switchTab,
        items: [
          _buildNavItem(Icons.home, '首页', 0),
          _buildNavItem(Icons.search, '搜索', 1),
          _buildNavItem(Icons.favorite, '收藏', 2),
          _buildNavItem(Icons.person, '我的', 3),
        ],
      ),
    );
  }

  BottomNavigationBarItem _buildNavItem(IconData icon, String label, int tabIndex) {
    return BottomNavigationBarItem(
      icon: AnimatedBuilder(
        animation: _jellyAnimation,
        builder: (context, child) {
          final animationValue = _jellyAnimation.value;
          // 选中项应用缩放+位移的果冻效果
          final scale = _currentTab == tabIndex 
              ? 1.0 + animationValue * 0.25 
              : 1.0;
          final translateY = _currentTab == tabIndex 
              ? -animationValue * 6 
              : 0.0;

          return Transform(
            transform: Matrix4.diagonal3Values(scale, scale, 1.0)
              ..translate(0, translateY),
            child: child,
          );
        },
        child: Icon(icon),
      ),
      label: label,
    );
  }
}

// 自定义弹簧曲线类
class SpringCurve extends Curve {
  final SpringSimulation simulation;

  SpringCurve(this.simulation);

  @override
  double transform(double t) {
    return simulation.x(t);
  }
}

参数调节说明

  • SpringDescription:
    • mass:质量越大,动画回弹越慢
    • stiffness:刚度越高,弹性越强
    • damping:阻尼越大,动画衰减越快
  • 动画时长:调整AnimationController的duration可以控制动画的快慢
  • 缩放/位移幅度:修改scale和translateY的乘数,能调整果冻效果的明显程度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 16:47:48